Revert "Merge branch 'disable-window-test' into 'master'"
authorMatthias Clasen <mclasen@redhat.com>
Thu, 19 Mar 2020 22:03:16 +0000 (18:03 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 19 Mar 2020 22:03:16 +0000 (18:03 -0400)
This reverts commit 3ac4c76b18cc89a841ce09f0943539f16988fd21, reversing
changes made to 6ec96d2e989d029a303b8b20ec72b86f974c0e87.

121 files changed:
demos/gtk-demo/demo.gresource.xml
demos/gtk-demo/fontplane.c
demos/gtk-demo/main.c
demos/gtk-demo/meson.build
demos/gtk-demo/shortcut_triggers.c [deleted file]
demos/gtk-demo/sliding_puzzle.c
docs/reference/gtk/gtk4-docs.xml
docs/reference/gtk/gtk4-sections.txt
docs/reference/gtk/gtk4.types.in
docs/tools/widgets.c
gdk/broadway/broadway.js
gdk/gdktypes.h
gtk/gtk.h
gtk/gtkaccelgroup.c
gtk/gtkaccelgroup.h
gtk/gtkaccelgroupprivate.h
gtk/gtkaccellabel.c
gtk/gtkaccellabel.h
gtk/gtkaccelmap.c [new file with mode: 0644]
gtk/gtkaccelmap.h [new file with mode: 0644]
gtk/gtkaccelmapprivate.h [new file with mode: 0644]
gtk/gtkapplication.c
gtk/gtkapplicationaccels.c
gtk/gtkapplicationaccelsprivate.h
gtk/gtkassistant.c
gtk/gtkbindings.c [new file with mode: 0644]
gtk/gtkbindings.h [new file with mode: 0644]
gtk/gtkbindingsprivate.h [new file with mode: 0644]
gtk/gtkbuilder.c
gtk/gtkcoloreditor.c
gtk/gtkcolorplane.c
gtk/gtkcolorscale.c
gtk/gtkcolorswatch.c
gtk/gtkcombobox.c
gtk/gtkconcatmodel.c [deleted file]
gtk/gtkconcatmodelprivate.h [deleted file]
gtk/gtkdialog.c
gtk/gtkemojichooser.c
gtk/gtkentry.c
gtk/gtkenums.h
gtk/gtkeventcontrollerfocus.c
gtk/gtkeventcontrollerkey.c
gtk/gtkfilechooserwidget.c
gtk/gtkflowbox.c
gtk/gtkiconview.c
gtk/gtkinfobar.c
gtk/gtklabel.c
gtk/gtklinkbutton.c
gtk/gtklistbox.c
gtk/gtkmain.c
gtk/gtkmnemonichash.c [new file with mode: 0644]
gtk/gtkmnemonichash.h [new file with mode: 0644]
gtk/gtkmodelbutton.c
gtk/gtkmountoperation.c
gtk/gtknotebook.c
gtk/gtkpaned.c
gtk/gtkpasswordentry.c
gtk/gtkplacesview.c
gtk/gtkplacesviewrow.c
gtk/gtkpopover.c
gtk/gtkpopovermenu.c
gtk/gtkrange.c
gtk/gtkroot.c
gtk/gtkscale.c
gtk/gtkscalebutton.c
gtk/gtkscrollbar.c
gtk/gtkscrolledwindow.c
gtk/gtksearchentry.c
gtk/gtkshortcut.c [deleted file]
gtk/gtkshortcut.h [deleted file]
gtk/gtkshortcutaction.c [deleted file]
gtk/gtkshortcutaction.h [deleted file]
gtk/gtkshortcutactionprivate.h [deleted file]
gtk/gtkshortcutcontroller.c [deleted file]
gtk/gtkshortcutcontroller.h [deleted file]
gtk/gtkshortcutcontrollerprivate.h [deleted file]
gtk/gtkshortcutlabel.c
gtk/gtkshortcutmanager.c [deleted file]
gtk/gtkshortcutmanager.h [deleted file]
gtk/gtkshortcutmanagerprivate.h [deleted file]
gtk/gtkshortcutssection.c
gtk/gtkshortcutswindow.c
gtk/gtkshortcuttrigger.c [deleted file]
gtk/gtkshortcuttrigger.h [deleted file]
gtk/gtkspinbutton.c
gtk/gtktext.c
gtk/gtktextview.c
gtk/gtktreeview.c
gtk/gtktypes.h
gtk/gtkwidget.c
gtk/gtkwidget.h
gtk/gtkwidgetprivate.h
gtk/gtkwindow.c
gtk/gtkwindow.h
gtk/gtkwindowprivate.h
gtk/inspector/init.c
gtk/inspector/meson.build
gtk/inspector/shortcuts.c [deleted file]
gtk/inspector/shortcuts.h [deleted file]
gtk/inspector/shortcuts.ui [deleted file]
gtk/inspector/window.c
gtk/inspector/window.h
gtk/inspector/window.ui
gtk/meson.build
gtk/ui/gtkcoloreditor.ui
gtk/ui/gtkfilechooserwidget.ui
gtk/ui/gtkplacesviewrow.ui
po-properties/POTFILES.in
po/POTFILES.in
tests/testgtk.c
tests/testmenubutton.c
testsuite/css/parser/at-invalid-22.css [new file with mode: 0644]
testsuite/css/parser/at-invalid-22.errors [new file with mode: 0644]
testsuite/css/parser/at-invalid-22.ref.css [new file with mode: 0644]
testsuite/css/parser/meson.build
testsuite/gtk/accel.c
testsuite/gtk/action.c
testsuite/gtk/builder.c
testsuite/gtk/concatmodel.c [deleted file]
testsuite/gtk/defaultvalue.c
testsuite/gtk/meson.build

index 7e4046cb6aaeab7347a3da091756371487d145f5..4dde63322ac46fcf4d5c3e18efe1f54b2c043363 100644 (file)
     <file>search_entry.c</file>
     <file>search_entry2.c</file>
     <file>shortcuts.c</file>
-    <file>shortcut_triggers.c</file>
     <file>sizegroup.c</file>
     <file>sidebar.c</file>
     <file>sliding_puzzle.c</file>
index 1f7e074adbcce6c2480bfe1c231b6c7ea8657a6e..b7b07cb7ada2388bc29afaa832bd06d754b7ef8e 100644 (file)
@@ -140,6 +140,17 @@ update_value (GtkFontPlane *plane,
   gtk_widget_queue_draw (widget);
 }
 
+static void
+hold_action (GtkGestureLongPress *gesture,
+             gdouble              x,
+             gdouble              y,
+             GtkFontPlane       *plane)
+{
+  gboolean handled;
+
+  g_signal_emit_by_name (plane, "popup-menu", &handled);
+}
+
 static void
 plane_drag_gesture_begin (GtkGestureDrag *gesture,
                           gdouble         start_x,
@@ -150,6 +161,13 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
 
   button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
 
+  if (button == GDK_BUTTON_SECONDARY)
+    {
+      gboolean handled;
+
+      g_signal_emit_by_name (plane, "popup-menu", &handled);
+    }
+
   if (button != GDK_BUTTON_PRIMARY)
     {
       gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
@@ -200,6 +218,13 @@ gtk_font_plane_init (GtkFontPlane *plane)
                    G_CALLBACK (plane_drag_gesture_end), plane);
   gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
   gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
+
+  gesture = gtk_gesture_long_press_new ();
+  g_signal_connect (gesture, "pressed",
+                    G_CALLBACK (hold_action), plane);
+  gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
+                                     TRUE);
+  gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
 }
 
 static void
index aef7b1922a37e6b7dace1eceea3c36157d9edc47..c552f9874e3ce518111ae39f08da5276b7d3cb73 100644 (file)
@@ -310,6 +310,7 @@ static const char *types[] =
   "GtkIconView ",
   "GtkCellRendererText ",
   "GtkContainer ",
+  "GtkAccelGroup ",
   "GtkPaned ",
   "GtkPrintOperation ",
   "GtkPrintContext ",
index 08694a73557018ec3a9a72aa36e42da9ee6fb23c..8dbd14cc2db09bbc2e0b5485c9c5103189bac762 100644 (file)
@@ -62,7 +62,6 @@ demos = files([
   'search_entry.c',
   'search_entry2.c',
   'shortcuts.c',
-  'shortcut_triggers.c',
   'sidebar.c',
   'sizegroup.c',
   'sliding_puzzle.c',
diff --git a/demos/gtk-demo/shortcut_triggers.c b/demos/gtk-demo/shortcut_triggers.c
deleted file mode 100644 (file)
index d5b59c3..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Shortcuts
- *
- * GtkShortcut is the abstraction used by GTK to handle shortcuts from
- * keyboard or other input devices.
- *
- * Shortcut triggers can be used to weave complex sequences of key
- * presses into sophisticated mechanisms to activate shortcuts.
- *
- * This demo code shows creative ways to do that.
- */
-
-#include <gtk/gtk.h>
-
-static GtkWidget *window = NULL;
-
-static gboolean
-shortcut_activated (GtkWidget *widget,
-                    GVariant  *unused,
-                    gpointer   row)
-{
-  g_print ("activated %s\n", gtk_label_get_label (row));
-  return TRUE;
-}
-
-static GtkShortcutTrigger *
-create_ctrl_g (void)
-{
-  return gtk_keyval_trigger_new (GDK_KEY_g, GDK_CONTROL_MASK);
-}
-
-static GtkShortcutTrigger *
-create_x (void)
-{
-  return gtk_keyval_trigger_new (GDK_KEY_x, 0);
-}
-
-struct {
-  const char *description;
-  GtkShortcutTrigger * (* create_trigger_func) (void);
-} shortcuts[] = {
-  { "Press Ctrl-G", create_ctrl_g },
-  { "Press X", create_x },
-};
-
-GtkWidget *
-do_shortcut_triggers (GtkWidget *do_widget)
-{
-  guint i;
-
-  if (!window)
-    {
-      GtkWidget *list;
-      GtkEventController *controller;
-
-      window = gtk_window_new ();
-      gtk_window_set_display (GTK_WINDOW (window),
-                              gtk_widget_get_display (do_widget));
-      gtk_window_set_title (GTK_WINDOW (window), "Shortcuts");
-
-      g_signal_connect (window, "destroy",
-                        G_CALLBACK (gtk_widget_destroyed), &window);
-
-      list = gtk_list_box_new ();
-      g_object_set (list, "margin", 6, NULL);
-      gtk_container_add (GTK_CONTAINER (window), list);
-
-      for (i = 0; i < G_N_ELEMENTS (shortcuts); i++)
-        {
-          GtkShortcut *shortcut;
-          GtkWidget *row;
-
-          row = gtk_label_new (shortcuts[i].description);
-          gtk_container_add (GTK_CONTAINER (list), row);
-
-          controller = gtk_shortcut_controller_new ();
-          gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller), GTK_SHORTCUT_SCOPE_GLOBAL);
-          gtk_widget_add_controller (row, controller);
-
-          shortcut = gtk_shortcut_new (shortcuts[i].create_trigger_func(),
-                                       gtk_callback_action_new (shortcut_activated, row, NULL));
-          gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-        }
-    }
-
-  if (!gtk_widget_get_visible (window))
-    gtk_widget_show (window);
-  else
-    gtk_widget_destroy (window);
-
-  return window;
-}
index 5dcc0351bc81d6c0fd8174fab09850a87ee107ce..0abb5c9f6ee40da6fe126e2b46f33471ff0d745b 100644 (file)
@@ -160,13 +160,47 @@ check_solved (GtkWidget *grid)
 }
 
 static gboolean
-puzzle_key_pressed (GtkWidget *grid,
-                    GVariant  *args,
-                    gpointer   unused)
+puzzle_key_pressed (GtkEventControllerKey *controller,
+                    guint                  keyval,
+                    guint                  keycode,
+                    GdkModifierType        state,
+                    GtkWidget             *grid)
 {
   int dx, dy;
 
-  g_variant_get (args, "(ii)", &dx, &dy);
+  dx = 0;
+  dy = 0;
+
+  switch (keyval)
+    {
+    case GDK_KEY_KP_Left:
+    case GDK_KEY_Left:
+      /* left */
+      dx = -1;
+      break;
+
+    case GDK_KEY_KP_Up:
+    case GDK_KEY_Up:
+      /* up */
+      dy = -1;
+      break;
+
+    case GDK_KEY_KP_Right:
+    case GDK_KEY_Right:
+      /* right */
+      dx = 1;
+      break;
+
+    case GDK_KEY_KP_Down:
+    case GDK_KEY_Down:
+      /* down */
+      dy = 1;
+      break;
+
+    default:
+      /* We return FALSE here because we didn't handle the key that was pressed */
+      return FALSE;
+    }
 
   if (!move_puzzle (grid, dx, dy))
     {
@@ -242,24 +276,6 @@ puzzle_button_pressed (GtkGestureClick *gesture,
     }
 }
 
-static void
-add_move_binding (GtkShortcutController *controller,
-                  guint                  keyval,
-                  guint                  kp_keyval,
-                  int                    dx,
-                  int                    dy)
-{
-  GtkShortcut *shortcut;
-
-  shortcut = gtk_shortcut_new_with_arguments (
-                 gtk_alternative_trigger_new (gtk_keyval_trigger_new (keyval, 0),
-                                              gtk_keyval_trigger_new (kp_keyval, 0)),
-                 gtk_callback_action_new (puzzle_key_pressed, NULL, NULL),
-                 "(ii)", dx, dy);
-  gtk_shortcut_controller_add_shortcut (controller, shortcut);
-  g_object_unref (shortcut);
-}
-
 static void
 start_puzzle (GdkPaintable *paintable)
 {
@@ -282,21 +298,12 @@ start_puzzle (GdkPaintable *paintable)
     aspect_ratio = 1.0;
   gtk_aspect_frame_set (GTK_ASPECT_FRAME (frame), 0.5, 0.5, aspect_ratio, FALSE);
 
-  /* Add shortcuts so people can use the arrow
+  /* Add a key event controller so people can use the arrow
    * keys to move the puzzle */
-  controller = gtk_shortcut_controller_new ();
-  add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
-                    GDK_KEY_Left, GDK_KEY_KP_Left,
-                    -1, 0);
-  add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
-                    GDK_KEY_Right, GDK_KEY_KP_Right,
-                    1, 0);
-  add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
-                    GDK_KEY_Up, GDK_KEY_KP_Up,
-                    0, -1);
-  add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
-                    GDK_KEY_Down, GDK_KEY_KP_Down,
-                    0, 1);
+  controller = gtk_event_controller_key_new ();
+  g_signal_connect (controller, "key-pressed",
+                    G_CALLBACK (puzzle_key_pressed),
+                    grid);
   gtk_widget_add_controller (GTK_WIDGET (grid), controller);
 
   controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
index 1bbcabc48bc5978bd704ce62a2fb2ec9260555e5..aabc016df4b4c56073193fb0737b790d88dff132 100644 (file)
       <xi:include href="xml/gtkgesturezoom.xml" />
       <xi:include href="xml/gtkgesturestylus.xml" />
       <xi:include href="xml/gtkpadcontroller.xml" />
-      <xi:include href="xml/gtkshortcutcontroller.xml" />
-    </chapter>
-
-    <chapter>
-      <title>Keyboard shortcuts</title>
-      <xi:include href="xml/gtkshortcut.xml" />
-      <xi:include href="xml/gtkshortcuttrigger.xml" />
-      <xi:include href="xml/gtkshortcutaction.xml" />
-      <xi:include href="xml/gtkshortcutmanager.xml" />
     </chapter>
 
     <chapter>
index 647fcafb5c47aac3fa07fd3ff7f318bc94dc130a..13b3f831f6a9069c4c400921fa28911ca443d904 100644 (file)
@@ -53,6 +53,26 @@ gtk_about_dialog_get_type
 <SECTION>
 <FILE>gtkaccelgroup</FILE>
 <TITLE>Keyboard Accelerators</TITLE>
+GtkAccelGroup
+GtkAccelGroupClass
+gtk_accel_group_new
+GtkAccelFlags
+gtk_accel_group_connect
+gtk_accel_group_connect_by_path
+GtkAccelGroupActivate
+GtkAccelGroupFindFunc
+gtk_accel_group_disconnect
+gtk_accel_group_disconnect_key
+gtk_accel_group_activate
+gtk_accel_group_lock
+gtk_accel_group_unlock
+gtk_accel_group_get_is_locked
+gtk_accel_group_from_accel_closure
+gtk_accel_group_get_modifier_mask
+gtk_accel_groups_activate
+gtk_accel_groups_from_object
+gtk_accel_group_find
+GtkAccelKey
 gtk_accelerator_valid
 gtk_accelerator_parse
 gtk_accelerator_name
@@ -62,6 +82,52 @@ gtk_accelerator_name_with_keycode
 gtk_accelerator_get_label_with_keycode
 gtk_accelerator_set_default_mod_mask
 gtk_accelerator_get_default_mod_mask
+
+<SUBSECTION Standard>
+GTK_TYPE_ACCEL_GROUP
+GTK_ACCEL_GROUP
+GTK_IS_ACCEL_GROUP
+GTK_ACCEL_GROUP_CLASS
+GTK_IS_ACCEL_GROUP_CLASS
+GTK_ACCEL_GROUP_GET_CLASS
+
+<SUBSECTION Private>
+GTK_ACCEL_GROUP_GET_PRIVATE
+GtkAccelGroupPrivate
+GtkAccelGroupEntry
+gtk_accel_group_query
+gtk_accel_group_get_type
+</SECTION>
+
+<SECTION>
+<FILE>gtkaccelmap</FILE>
+<TITLE>Accelerator Maps</TITLE>
+GtkAccelMap
+GtkAccelMapForeach
+gtk_accel_map_add_entry
+gtk_accel_map_lookup_entry
+gtk_accel_map_change_entry
+gtk_accel_map_load
+gtk_accel_map_save
+gtk_accel_map_foreach
+gtk_accel_map_load_fd
+gtk_accel_map_save_fd
+gtk_accel_map_load_scanner
+gtk_accel_map_add_filter
+gtk_accel_map_foreach_unfiltered
+gtk_accel_map_get
+gtk_accel_map_lock_path
+gtk_accel_map_unlock_path
+<SUBSECTION Standard>
+GTK_ACCEL_MAP
+GTK_TYPE_ACCEL_MAP
+GTK_IS_ACCEL_MAP
+GTK_ACCEL_MAP_CLASS
+GTK_IS_ACCEL_MAP_CLASS
+GTK_ACCEL_MAP_GET_CLASS
+GtkAccelMapClass
+<SUBSECTION Private>
+gtk_accel_map_get_type
 </SECTION>
 
 <SECTION>
@@ -69,6 +135,10 @@ gtk_accelerator_get_default_mod_mask
 <TITLE>GtkAccelLabel</TITLE>
 GtkAccelLabel
 gtk_accel_label_new
+gtk_accel_label_set_accel_closure
+gtk_accel_label_get_accel_closure
+gtk_accel_label_get_accel_widget
+gtk_accel_label_set_accel_widget
 gtk_accel_label_get_accel_width
 gtk_accel_label_set_accel
 gtk_accel_label_get_accel
@@ -3964,9 +4034,10 @@ gtk_widget_add_tick_callback
 gtk_widget_remove_tick_callback
 gtk_widget_size_allocate
 gtk_widget_allocate
-gtk_widget_class_add_shortcut
-gtk_widget_class_add_binding
-gtk_widget_class_add_binding_signal
+gtk_widget_add_accelerator
+gtk_widget_remove_accelerator
+gtk_widget_set_accel_path
+gtk_widget_list_accel_closures
 gtk_widget_can_activate_accel
 gtk_widget_activate
 gtk_widget_is_focus
@@ -4182,6 +4253,8 @@ gtk_window_new
 gtk_window_set_title
 gtk_window_set_resizable
 gtk_window_get_resizable
+gtk_window_add_accel_group
+gtk_window_remove_accel_group
 gtk_window_set_modal
 gtk_window_set_default_size
 gtk_window_set_hide_on_close
@@ -4193,6 +4266,11 @@ gtk_window_is_active
 gtk_window_is_maximized
 gtk_window_get_toplevels
 gtk_window_list_toplevels
+gtk_window_add_mnemonic
+gtk_window_remove_mnemonic
+gtk_window_mnemonic_activate
+gtk_window_activate_key
+gtk_window_propagate_key_event
 gtk_window_get_focus
 gtk_window_set_focus
 gtk_window_get_default_widget
@@ -4213,6 +4291,7 @@ gtk_window_set_keep_above
 gtk_window_set_keep_below
 gtk_window_set_decorated
 gtk_window_set_deletable
+gtk_window_set_mnemonic_modifier
 gtk_window_set_accept_focus
 gtk_window_set_focus_on_map
 gtk_window_set_startup_id
@@ -4222,6 +4301,7 @@ gtk_window_get_default_icon_name
 gtk_window_get_default_size
 gtk_window_get_destroy_with_parent
 gtk_window_get_icon_name
+gtk_window_get_mnemonic_modifier
 gtk_window_get_modal
 gtk_window_get_size
 gtk_window_get_title
@@ -4537,6 +4617,26 @@ gtk_css_provider_error_quark
 gtk_css_section_get_type
 </SECTION>
 
+<SECTION>
+<FILE>gtkbindings</FILE>
+<TITLE>Bindings</TITLE>
+GtkBindingSet
+gtk_binding_set_new
+gtk_binding_set_by_class
+gtk_binding_set_find
+gtk_bindings_activate
+gtk_bindings_activate_event
+gtk_binding_set_activate
+gtk_binding_entry_add_action
+gtk_binding_entry_add_action_variant
+GtkBindingCallback
+gtk_binding_entry_add_callback
+gtk_binding_entry_add_signal
+gtk_binding_entry_add_signal_from_string
+gtk_binding_entry_skip
+gtk_binding_entry_remove
+</SECTION>
+
 <SECTION>
 <FILE>gtkenums</FILE>
 <TITLE>Standard Enumerations</TITLE>
@@ -5961,144 +6061,6 @@ GTK_EVENT_CONTROLLER_MOTION_GET_CLASS
 gtk_event_controller_motion_get_type
 </SECTION>
 
-<SECTION>
-<FILE>gtkshortcuttrigger</FILE>
-<TITLE>GtkShortcutTrigger</TITLE>
-GtkShortcutTrigger
-gtk_shortcut_trigger_ref
-gtk_shortcut_trigger_unref
-GtkShortcutTriggerType
-gtk_shortcut_trigger_get_trigger_type
-gtk_shortcut_trigger_parse_string
-gtk_shortcut_trigger_trigger
-gtk_shortcut_trigger_hash
-gtk_shortcut_trigger_equal
-gtk_shortcut_trigger_compare
-gtk_shortcut_trigger_to_string
-gtk_shortcut_trigger_print
-gtk_shortcut_trigger_to_label
-gtk_shortcut_trigger_print_label
-
-<SUBSECTION>
-gtk_keyval_trigger_new
-gtk_keyval_trigger_get_modifiers
-gtk_keyval_trigger_get_keyval
-
-<SUBSECTION>
-gtk_mnemonic_trigger_new
-gtk_mnemonic_trigger_get_keyval
-
-<SUBSECTION Private>
-gtk_shortcut_trigger_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcutaction</FILE>
-<TITLE>GtkShortcutAction</TITLE>
-GtkShortcutAction
-gtk_shortcut_action_ref
-gtk_shortcut_action_unref
-GtkShortcutActionType
-gtk_shortcut_action_get_action_type
-gtk_shortcut_action_to_string
-gtk_shortcut_action_print
-gtk_shortcut_action_activate
-
-<SUBSECTION>
-gtk_nothing_action_new
-
-<SUBSECTION>
-gtk_callback_action_new
-
-<SUBSECTION>
-gtk_mnemonic_action_new
-
-<SUBSECTION>
-gtk_activate_action_new
-
-<SUBSECTION>
-gtk_signal_action_new
-gtk_signal_action_get_signal_name
-
-<SUBSECTION>
-gtk_action_action_new
-gtk_action_action_get_name
-
-<SUBSECTION>
-gtk_gaction_action_new
-gtk_gaction_action_get_gaction
-
-<SUBSECTION Private>
-gtk_shortcut_action_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcut</FILE>
-<TITLE>GtkShortcut</TITLE>
-GtkShortcut
-gtk_shortcut_new
-gtk_shortcut_new_with_arguments
-gtk_shortcut_get_trigger
-gtk_shortcut_set_trigger
-gtk_shortcut_get_action
-gtk_shortcut_set_action
-gtk_shortcut_get_arguments
-gtk_shortcut_set_arguments
-
-<SUBSECTION Standard>
-GTK_TYPE_SHORTCUT
-GTK_SHORTCUT
-GTK_SHORTCUT_CLASS
-GTK_IS_SHORTCUT
-GTK_IS_SHORTCUT_CLASS
-GTK_SHORTCUT_GET_CLASS
-
-<SUBSECTION Private>
-gtk_shortcut_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcutmanager</FILE>
-<TITLE>GtkShortcutManager</TITLE>
-GtkShortcutManager
-GtkShortcutManagerInterface
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcutcontroller</FILE>
-<TITLE>GtkShortcutController</TITLE>
-GtkShortcutController
-gtk_shortcut_controller_new
-gtk_shortcut_controller_new_with_model
-GtkShortcutScope
-GtkShortcutManager
-GtkShortcutManagerInterface
-gtk_shortcut_controller_set_mnemonics_modifiers
-gtk_shortcut_controller_get_mnemonics_modifiers
-gtk_shortcut_controller_set_scope
-gtk_shortcut_controller_get_scope
-gtk_shortcut_controller_add_shortcut
-gtk_shortcut_controller_remove_shortcut
-
-<SUBSECTION Standard>
-GTK_TYPE_SHORTCUT_CONTROLLER
-GTK_SHORTCUT_CONTROLLER
-GTK_SHORTCUT_CONTROLLER_CLASS
-GTK_IS_SHORTCUT_CONTROLLER
-GTK_IS_SHORTCUT_CONTROLLER_CLASS
-GTK_SHORTCUT_CONTROLLER_GET_CLASS
-GTK_TYPE_SHORTCUT_MANAGER
-GTK_SHORTCUT_MANAGER
-GTK_SHORTCUT_MANAGER_CLASS
-GTK_IS_SHORTCUT_MANAGER
-GTK_IS_SHORTCUT_MANAGER_CLASS
-GTK_SHORTCUT_MANAGER_GET_CLASS
-
-<SUBSECTION Private>
-gtk_shortcut_controller_get_type
-gtk_shortcut_manager_get_type
-</SECTION>
-
 <SECTION>
 <FILE>gtkeventcontrollerkey</FILE>
 <TITLE>GtkEventControllerKey</TITLE>
index d7d9b0106b33d32d35c7adc762c335960f8b18b7..1c7b9eabb207c251061cab328cb043ed3db8e2af 100644 (file)
@@ -2,7 +2,9 @@
 #include <gtk/gtkunixprint.h>
 
 gtk_about_dialog_get_type
+gtk_accel_group_get_type
 gtk_accel_label_get_type
+gtk_accel_map_get_type
 gtk_accessible_get_type
 gtk_actionable_get_type
 gtk_action_bar_get_type
@@ -163,10 +165,7 @@ gtk_search_entry_get_type
 gtk_selection_model_get_type
 gtk_separator_get_type
 gtk_settings_get_type
-gtk_shortcut_get_type
-gtk_shortcut_controller_get_type
 gtk_shortcut_label_get_type
-gtk_shortcut_manager_get_type
 gtk_shortcuts_window_get_type
 gtk_shortcuts_section_get_type
 gtk_shortcuts_group_get_type
index 7b6367736803d3ffd63d76b865c3cdfb6698cb91..fba3e02a0abcc209972e4fd79857f92f53ded9bf 100644 (file)
@@ -281,20 +281,26 @@ create_accel_label (void)
 {
   WidgetInfo *info;
   GtkWidget *widget, *button, *box;
+  GtkAccelGroup *accel_group;
 
   widget = gtk_accel_label_new ("Accel Label");
 
   button = gtk_button_new_with_label ("Quit");
+  gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (widget), button);
   gtk_widget_hide (button);
 
   box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
   gtk_container_add (GTK_CONTAINER (box), widget);
   gtk_container_add (GTK_CONTAINER (box), button);
 
-  gtk_accel_label_set_accel (GTK_ACCEL_LABEL (widget), GDK_KEY_Q, GDK_CONTROL_MASK);
+  gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (widget), button);
+  accel_group = gtk_accel_group_new();
 
   info = new_widget_info ("accel-label", box, SMALL);
 
+  gtk_widget_add_accelerator (button, "activate", accel_group, GDK_KEY_Q, GDK_CONTROL_MASK,
+                             GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
+
   return info;
 }
 
index 6cb576d40c3ff47fbab5b677a0d5966cdc9cac17..267ef205ee16ccba1fe97aa5f931af299944f544 100644 (file)
@@ -75,7 +75,7 @@ const GDK_CROSSING_GRAB = 1;
 const GDK_CROSSING_UNGRAB = 2;
 
 // GdkModifierType
-const GDK_SHIFT_MASK    = 1 << 0;
+const GDK_SHIFT_MASK = 1 << 0;
 const GDK_LOCK_MASK     = 1 << 1;
 const GDK_CONTROL_MASK  = 1 << 2;
 const GDK_MOD1_MASK     = 1 << 3;
@@ -91,6 +91,7 @@ const GDK_BUTTON5_MASK  = 1 << 12;
 const GDK_SUPER_MASK    = 1 << 26;
 const GDK_HYPER_MASK    = 1 << 27;
 const GDK_META_MASK     = 1 << 28;
+const GDK_RELEASE_MASK  = 1 << 30;
 
 
 var useDataUrls = window.location.search.includes("datauri");
index 7eb74b080f00f858e4e96a0aa8a16f76c835d231..5b0f6be7ccda4b4986a45b29e178b9b5f2abfec1 100644 (file)
@@ -232,7 +232,8 @@ typedef enum
  * @GDK_HYPER_MASK: the Hyper modifier
  * @GDK_META_MASK: the Meta modifier
  * @GDK_MODIFIER_RESERVED_29_MASK: A reserved bit flag; do not use in your own code
- * @GDK_MODIFIER_RESERVED_30_MASK: A reserved bit flag; do not use in your own code
+ * @GDK_RELEASE_MASK: not used in GDK itself. GTK uses it to differentiate
+ *  between (keyval, modifiers) pairs from key press and release events.
  * @GDK_MODIFIER_MASK: a mask covering all modifier types.
  *
  * A set of bit-flags to indicate the state of modifier keys and mouse buttons
@@ -293,11 +294,12 @@ typedef enum
   GDK_META_MASK     = 1 << 28,
   
   GDK_MODIFIER_RESERVED_29_MASK  = 1 << 29,
-  GDK_MODIFIER_RESERVED_30_MASK  = 1 << 30,
+
+  GDK_RELEASE_MASK  = 1 << 30,
 
   /* Combination of GDK_SHIFT_MASK..GDK_BUTTON5_MASK + GDK_SUPER_MASK
-     + GDK_HYPER_MASK + GDK_META_MASK */
-  GDK_MODIFIER_MASK = 0x1c001fff
+     + GDK_HYPER_MASK + GDK_META_MASK + GDK_RELEASE_MASK */
+  GDK_MODIFIER_MASK = 0x5c001fff
 } GdkModifierType;
 
 /**
index 8fe078e6a96578ca358ab41745309e188da2f4e5..603fe9f9fd6e172cebd1401d52d5b412d5b97988 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -34,6 +34,7 @@
 #include <gtk/gtkaboutdialog.h>
 #include <gtk/gtkaccelgroup.h>
 #include <gtk/gtkaccellabel.h>
+#include <gtk/gtkaccelmap.h>
 #include <gtk/gtkaccessible.h>
 #include <gtk/gtkactionable.h>
 #include <gtk/gtkactionbar.h>
@@ -48,6 +49,7 @@
 #include <gtk/gtkassistant.h>
 #include <gtk/gtkbin.h>
 #include <gtk/gtkbinlayout.h>
+#include <gtk/gtkbindings.h>
 #include <gtk/gtkborder.h>
 #include <gtk/gtkboxlayout.h>
 #include <gtk/gtkbox.h>
 #include <gtk/gtkselectionmodel.h>
 #include <gtk/gtkseparator.h>
 #include <gtk/gtksettings.h>
-#include <gtk/gtkshortcut.h>
-#include <gtk/gtkshortcutaction.h>
-#include <gtk/gtkshortcutcontroller.h>
 #include <gtk/gtkshortcutlabel.h>
-#include <gtk/gtkshortcutmanager.h>
 #include <gtk/gtkshortcutsgroup.h>
 #include <gtk/gtkshortcutssection.h>
 #include <gtk/gtkshortcutsshortcut.h>
 #include <gtk/gtkshortcutswindow.h>
-#include <gtk/gtkshortcuttrigger.h>
 #include <gtk/gtkshow.h>
 #include <gtk/gtksingleselection.h>
 #include <gtk/gtkslicelistmodel.h>
index 553ec84ce315887c0c6fb1e6d554571b3d5318a2..dbf4e261af739e4d20e3e1981246f11ca251a9fe 100644 (file)
@@ -29,6 +29,7 @@
 #include "gtkaccelgroup.h"
 #include "gtkaccelgroupprivate.h"
 #include "gtkaccellabelprivate.h"
+#include "gtkaccelmapprivate.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
  * and mnemonics, of course.
  */
 
+/* --- prototypes --- */
+static void gtk_accel_group_finalize     (GObject    *object);
+static void gtk_accel_group_get_property (GObject    *object,
+                                          guint       param_id,
+                                          GValue     *value,
+                                          GParamSpec *pspec);
+static void accel_closure_invalidate     (gpointer    data,
+                                          GClosure   *closure);
+
+
 /* --- variables --- */
+static guint  signal_accel_activate      = 0;
+static guint  signal_accel_changed       = 0;
+static guint  quark_acceleratable_groups = 0;
 static guint  default_accel_mod_mask     = 0;
 
+enum {
+  PROP_0,
+  PROP_IS_LOCKED,
+  PROP_MODIFIER_MASK,
+  N_PROPERTIES
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelGroup, gtk_accel_group, G_TYPE_OBJECT)
+
 
 /* --- functions --- */
+static void
+gtk_accel_group_class_init (GtkAccelGroupClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  quark_acceleratable_groups = g_quark_from_static_string ("gtk-acceleratable-accel-groups");
+
+  object_class->finalize = gtk_accel_group_finalize;
+  object_class->get_property = gtk_accel_group_get_property;
+
+  class->accel_changed = NULL;
+
+  obj_properties [PROP_IS_LOCKED] =
+    g_param_spec_boolean ("is-locked",
+                          "Is locked",
+                          "Is the accel group locked",
+                          FALSE,
+                          G_PARAM_READABLE);
+
+  obj_properties [PROP_MODIFIER_MASK] =
+    g_param_spec_flags ("modifier-mask",
+                        "Modifier Mask",
+                        "Modifier Mask",
+                        GDK_TYPE_MODIFIER_TYPE,
+                        default_accel_mod_mask,
+                        G_PARAM_READABLE);
+
+   g_object_class_install_properties (object_class,
+                                      N_PROPERTIES,
+                                      obj_properties);
+
+  /**
+   * GtkAccelGroup::accel-activate:
+   * @accel_group: the #GtkAccelGroup which received the signal
+   * @acceleratable: the object on which the accelerator was activated
+   * @keyval: the accelerator keyval
+   * @modifier: the modifier combination of the accelerator
+   *
+   * The accel-activate signal is an implementation detail of
+   * #GtkAccelGroup and not meant to be used by applications.
+   *
+   * Returns: %TRUE if the accelerator was activated
+   */
+  signal_accel_activate =
+    g_signal_new (I_("accel-activate"),
+                  G_OBJECT_CLASS_TYPE (class),
+                  G_SIGNAL_DETAILED,
+                  0,
+                  _gtk_boolean_handled_accumulator, NULL,
+                  _gtk_marshal_BOOLEAN__OBJECT_UINT_FLAGS,
+                  G_TYPE_BOOLEAN, 3,
+                  G_TYPE_OBJECT,
+                  G_TYPE_UINT,
+                  GDK_TYPE_MODIFIER_TYPE);
+  /**
+   * GtkAccelGroup::accel-changed:
+   * @accel_group: the #GtkAccelGroup which received the signal
+   * @keyval: the accelerator keyval
+   * @modifier: the modifier combination of the accelerator
+   * @accel_closure: the #GClosure of the accelerator
+   *
+   * The accel-changed signal is emitted when an entry
+   * is added to or removed from the accel group.
+   *
+   * Widgets like #GtkAccelLabel which display an associated
+   * accelerator should connect to this signal, and rebuild
+   * their visual representation if the @accel_closure is theirs.
+   */
+  signal_accel_changed =
+    g_signal_new (I_("accel-changed"),
+                  G_OBJECT_CLASS_TYPE (class),
+                  G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+                  G_STRUCT_OFFSET (GtkAccelGroupClass, accel_changed),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__UINT_FLAGS_BOXED,
+                  G_TYPE_NONE, 3,
+                  G_TYPE_UINT,
+                  GDK_TYPE_MODIFIER_TYPE,
+                  G_TYPE_CLOSURE);
+}
+
+static void
+gtk_accel_group_finalize (GObject *object)
+{
+  GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
+  guint i;
+
+  for (i = 0; i < accel_group->priv->n_accels; i++)
+    {
+      GtkAccelGroupEntry *entry = &accel_group->priv->priv_accels[i];
+
+      if (entry->accel_path_quark)
+        {
+          const gchar *accel_path = g_quark_to_string (entry->accel_path_quark);
+
+          _gtk_accel_map_remove_group (accel_path, accel_group);
+        }
+      g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate);
+
+      /* remove quick_accel_add() refcount */
+      g_closure_unref (entry->closure);
+    }
+
+  g_free (accel_group->priv->priv_accels);
+
+  G_OBJECT_CLASS (gtk_accel_group_parent_class)->finalize (object);
+}
+
+static void
+gtk_accel_group_get_property (GObject    *object,
+                              guint       param_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
+
+  switch (param_id)
+    {
+    case PROP_IS_LOCKED:
+      g_value_set_boolean (value, accel_group->priv->lock_count > 0);
+      break;
+    case PROP_MODIFIER_MASK:
+      g_value_set_flags (value, accel_group->priv->modifier_mask);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_accel_group_init (GtkAccelGroup *accel_group)
+{
+  GtkAccelGroupPrivate *priv;
+
+  accel_group->priv = gtk_accel_group_get_instance_private (accel_group);
+  priv = accel_group->priv;
+
+  priv->lock_count = 0;
+  priv->modifier_mask = gtk_accelerator_get_default_mod_mask ();
+  priv->acceleratables = NULL;
+  priv->n_accels = 0;
+  priv->priv_accels = NULL;
+}
+
+/**
+ * gtk_accel_group_new:
+ *
+ * Creates a new #GtkAccelGroup.
+ *
+ * Returns: a new #GtkAccelGroup object
+ */
+GtkAccelGroup*
+gtk_accel_group_new (void)
+{
+  return g_object_new (GTK_TYPE_ACCEL_GROUP, NULL);
+}
+
+/**
+ * gtk_accel_group_get_is_locked:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Locks are added and removed using gtk_accel_group_lock() and
+ * gtk_accel_group_unlock().
+ *
+ * Returns: %TRUE if there are 1 or more locks on the @accel_group,
+ *     %FALSE otherwise.
+ */
+gboolean
+gtk_accel_group_get_is_locked (GtkAccelGroup *accel_group)
+{
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+  return accel_group->priv->lock_count > 0;
+}
+
+/**
+ * gtk_accel_group_get_modifier_mask:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Gets a #GdkModifierType representing the mask for this
+ * @accel_group. For example, #GDK_CONTROL_MASK, #GDK_SHIFT_MASK, etc.
+ *
+ * Returns: the modifier mask for this accel group.
+ */
+GdkModifierType
+gtk_accel_group_get_modifier_mask (GtkAccelGroup *accel_group)
+{
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), 0);
+
+  return accel_group->priv->modifier_mask;
+}
+
+static void
+accel_group_weak_ref_detach (GSList  *free_list,
+                             GObject *stale_object)
+{
+  GSList *slist;
+
+  for (slist = free_list; slist; slist = slist->next)
+    {
+      GtkAccelGroup *accel_group;
+
+      accel_group = slist->data;
+      accel_group->priv->acceleratables = g_slist_remove (accel_group->priv->acceleratables, stale_object);
+      g_object_unref (accel_group);
+    }
+  g_slist_free (free_list);
+  g_object_set_qdata (stale_object, quark_acceleratable_groups, NULL);
+}
+
+void
+_gtk_accel_group_attach (GtkAccelGroup *accel_group,
+                         GObject       *object)
+{
+  GSList *slist;
+
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (G_IS_OBJECT (object));
+  g_return_if_fail (g_slist_find (accel_group->priv->acceleratables, object) == NULL);
+
+  g_object_ref (accel_group);
+  accel_group->priv->acceleratables = g_slist_prepend (accel_group->priv->acceleratables, object);
+  slist = g_object_get_qdata (object, quark_acceleratable_groups);
+  if (slist)
+    g_object_weak_unref (object,
+                         (GWeakNotify) accel_group_weak_ref_detach,
+                         slist);
+  slist = g_slist_prepend (slist, accel_group);
+  g_object_set_qdata (object, quark_acceleratable_groups, slist);
+  g_object_weak_ref (object,
+                     (GWeakNotify) accel_group_weak_ref_detach,
+                     slist);
+}
+
+void
+_gtk_accel_group_detach (GtkAccelGroup *accel_group,
+                         GObject       *object)
+{
+  GSList *slist;
+
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (G_IS_OBJECT (object));
+  g_return_if_fail (g_slist_find (accel_group->priv->acceleratables, object) != NULL);
+
+  accel_group->priv->acceleratables = g_slist_remove (accel_group->priv->acceleratables, object);
+  slist = g_object_get_qdata (object, quark_acceleratable_groups);
+  g_object_weak_unref (object,
+                       (GWeakNotify) accel_group_weak_ref_detach,
+                       slist);
+  slist = g_slist_remove (slist, accel_group);
+  g_object_set_qdata (object, quark_acceleratable_groups, slist);
+  if (slist)
+    g_object_weak_ref (object,
+                       (GWeakNotify) accel_group_weak_ref_detach,
+                       slist);
+  g_object_unref (accel_group);
+}
+
+/**
+ * gtk_accel_groups_from_object:
+ * @object: a #GObject, usually a #GtkWindow
+ *
+ * Gets a list of all accel groups which are attached to @object.
+ *
+ * Returns: (element-type GtkAccelGroup) (transfer none): a list of
+ *     all accel groups which are attached to @object
+ */
+GSList*
+gtk_accel_groups_from_object (GObject *object)
+{
+  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+
+  return g_object_get_qdata (object, quark_acceleratable_groups);
+}
+
+/**
+ * gtk_accel_group_find:
+ * @accel_group: a #GtkAccelGroup
+ * @find_func: (scope call): a function to filter the entries
+ *    of @accel_group with
+ * @data: data to pass to @find_func
+ *
+ * Finds the first entry in an accelerator group for which
+ * @find_func returns %TRUE and returns its #GtkAccelKey.
+ *
+ * Returns: (transfer none): the key of the first entry passing
+ *    @find_func. The key is owned by GTK+ and must not be freed.
+ */
+GtkAccelKey*
+gtk_accel_group_find (GtkAccelGroup         *accel_group,
+                      GtkAccelGroupFindFunc  find_func,
+                      gpointer               data)
+{
+  GtkAccelKey *key = NULL;
+  guint i;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+  g_return_val_if_fail (find_func != NULL, NULL);
+
+  g_object_ref (accel_group);
+  for (i = 0; i < accel_group->priv->n_accels; i++)
+    if (find_func (&accel_group->priv->priv_accels[i].key,
+                   accel_group->priv->priv_accels[i].closure,
+                   data))
+      {
+        key = &accel_group->priv->priv_accels[i].key;
+        break;
+      }
+  g_object_unref (accel_group);
+
+  return key;
+}
+
+/**
+ * gtk_accel_group_lock:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Locks the given accelerator group.
+ *
+ * Locking an acelerator group prevents the accelerators contained
+ * within it to be changed during runtime. Refer to
+ * gtk_accel_map_change_entry() about runtime accelerator changes.
+ *
+ * If called more than once, @accel_group remains locked until
+ * gtk_accel_group_unlock() has been called an equivalent number
+ * of times.
+ */
+void
+gtk_accel_group_lock (GtkAccelGroup *accel_group)
+{
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  accel_group->priv->lock_count += 1;
+
+  if (accel_group->priv->lock_count == 1) {
+    /* State change from unlocked to locked */
+    g_object_notify_by_pspec (G_OBJECT (accel_group), obj_properties[PROP_IS_LOCKED]);
+  }
+}
+
+/**
+ * gtk_accel_group_unlock:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Undoes the last call to gtk_accel_group_lock() on this @accel_group.
+ */
+void
+gtk_accel_group_unlock (GtkAccelGroup *accel_group)
+{
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (accel_group->priv->lock_count > 0);
+
+  accel_group->priv->lock_count -= 1;
+
+  if (accel_group->priv->lock_count < 1) {
+    /* State change from locked to unlocked */
+    g_object_notify_by_pspec (G_OBJECT (accel_group), obj_properties[PROP_IS_LOCKED]);
+  }
+}
+
+static void
+accel_closure_invalidate (gpointer  data,
+                          GClosure *closure)
+{
+  GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (data);
+
+  gtk_accel_group_disconnect (accel_group, closure);
+}
+
+static int
+bsearch_compare_accels (const void *d1,
+                        const void *d2)
+{
+  const GtkAccelGroupEntry *entry1 = d1;
+  const GtkAccelGroupEntry *entry2 = d2;
+
+  if (entry1->key.accel_key == entry2->key.accel_key)
+    return entry1->key.accel_mods < entry2->key.accel_mods ? -1 : entry1->key.accel_mods > entry2->key.accel_mods;
+  else
+    return entry1->key.accel_key < entry2->key.accel_key ? -1 : 1;
+}
+
+static void
+quick_accel_add (GtkAccelGroup   *accel_group,
+                 guint            accel_key,
+                 GdkModifierType  accel_mods,
+                 GtkAccelFlags    accel_flags,
+                 GClosure        *closure,
+                 GQuark           path_quark)
+{
+  guint pos, i = accel_group->priv->n_accels++;
+  GtkAccelGroupEntry key;
+
+  /* find position */
+  key.key.accel_key = accel_key;
+  key.key.accel_mods = accel_mods;
+  for (pos = 0; pos < i; pos++)
+    if (bsearch_compare_accels (&key, accel_group->priv->priv_accels + pos) < 0)
+      break;
+
+  /* insert at position, ref closure */
+  accel_group->priv->priv_accels = g_renew (GtkAccelGroupEntry, accel_group->priv->priv_accels, accel_group->priv->n_accels);
+  memmove (accel_group->priv->priv_accels + pos + 1, accel_group->priv->priv_accels + pos,
+           (i - pos) * sizeof (accel_group->priv->priv_accels[0]));
+  accel_group->priv->priv_accels[pos].key.accel_key = accel_key;
+  accel_group->priv->priv_accels[pos].key.accel_mods = accel_mods;
+  accel_group->priv->priv_accels[pos].key.accel_flags = accel_flags;
+  accel_group->priv->priv_accels[pos].closure = g_closure_ref (closure);
+  accel_group->priv->priv_accels[pos].accel_path_quark = path_quark;
+  g_closure_sink (closure);
+
+  /* handle closure invalidation and reverse lookups */
+  g_closure_add_invalidate_notifier (closure, accel_group, accel_closure_invalidate);
+
+  /* get accel path notification */
+  if (path_quark)
+    _gtk_accel_map_add_group (g_quark_to_string (path_quark), accel_group);
+
+  /* connect and notify changed */
+  if (accel_key)
+    {
+      gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods);
+      GQuark accel_quark = g_quark_from_string (accel_name);
+
+      g_free (accel_name);
+
+      /* setup handler */
+      g_signal_connect_closure_by_id (accel_group, signal_accel_activate, accel_quark, closure, FALSE);
+
+      /* and notify */
+      g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
+    }
+}
+
+static void
+quick_accel_remove (GtkAccelGroup *accel_group,
+                    guint          pos)
+{
+  GQuark accel_quark = 0;
+  GtkAccelGroupEntry *entry = accel_group->priv->priv_accels + pos;
+  guint accel_key = entry->key.accel_key;
+  GdkModifierType accel_mods = entry->key.accel_mods;
+  GClosure *closure = entry->closure;
+
+  /* quark for notification */
+  if (accel_key)
+    {
+      gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods);
+
+      accel_quark = g_quark_from_string (accel_name);
+      g_free (accel_name);
+    }
+
+  /* clean up closure invalidate notification and disconnect */
+  g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate);
+  if (accel_quark)
+    g_signal_handlers_disconnect_matched (accel_group,
+                                          G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_CLOSURE,
+                                          signal_accel_activate, accel_quark,
+                                          closure, NULL, NULL);
+  /* clean up accel path notification */
+  if (entry->accel_path_quark)
+    _gtk_accel_map_remove_group (g_quark_to_string (entry->accel_path_quark), accel_group);
+
+  /* physically remove */
+  accel_group->priv->n_accels -= 1;
+  memmove (entry, entry + 1,
+           (accel_group->priv->n_accels - pos) * sizeof (accel_group->priv->priv_accels[0]));
+
+  /* and notify */
+  if (accel_quark)
+    g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
+
+  /* remove quick_accel_add() refcount */
+  g_closure_unref (closure);
+}
+
+static GtkAccelGroupEntry*
+quick_accel_find (GtkAccelGroup   *accel_group,
+                  guint            accel_key,
+                  GdkModifierType  accel_mods,
+                  guint           *count_p)
+{
+  GtkAccelGroupEntry *entry;
+  GtkAccelGroupEntry key;
+
+  *count_p = 0;
+
+  if (!accel_group->priv->n_accels)
+    return NULL;
+
+  key.key.accel_key = accel_key;
+  key.key.accel_mods = accel_mods;
+  entry = bsearch (&key, accel_group->priv->priv_accels, accel_group->priv->n_accels,
+                   sizeof (accel_group->priv->priv_accels[0]), bsearch_compare_accels);
+
+  if (!entry)
+    return NULL;
+
+  /* step back to the first member */
+  for (; entry > accel_group->priv->priv_accels; entry--)
+    if (entry[-1].key.accel_key != accel_key ||
+        entry[-1].key.accel_mods != accel_mods)
+      break;
+  /* count equal members */
+  for (; entry + *count_p < accel_group->priv->priv_accels + accel_group->priv->n_accels; (*count_p)++)
+    if (entry[*count_p].key.accel_key != accel_key ||
+        entry[*count_p].key.accel_mods != accel_mods)
+      break;
+  return entry;
+}
+
+/**
+ * gtk_accel_group_connect:
+ * @accel_group: the accelerator group to install an accelerator in
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ * @accel_flags: a flag mask to configure this accelerator
+ * @closure: closure to be executed upon accelerator activation
+ *
+ * Installs an accelerator in this group. When @accel_group is being
+ * activated in response to a call to gtk_accel_groups_activate(),
+ * @closure will be invoked if the @accel_key and @accel_mods from
+ * gtk_accel_groups_activate() match those of this connection.
+ *
+ * The signature used for the @closure is that of #GtkAccelGroupActivate.
+ *
+ * Note that, due to implementation details, a single closure can
+ * only be connected to one accelerator group.
+ */
+void
+gtk_accel_group_connect (GtkAccelGroup   *accel_group,
+                         guint            accel_key,
+                         GdkModifierType  accel_mods,
+                         GtkAccelFlags    accel_flags,
+                         GClosure        *closure)
+{
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (closure != NULL);
+  g_return_if_fail (accel_key > 0);
+  g_return_if_fail (gtk_accel_group_from_accel_closure (closure) == NULL);
+
+  g_object_ref (accel_group);
+  if (!closure->is_invalid)
+    quick_accel_add (accel_group,
+                     gdk_keyval_to_lower (accel_key),
+                     accel_mods, accel_flags, closure, 0);
+  g_object_unref (accel_group);
+}
+
+/**
+ * gtk_accel_group_connect_by_path:
+ * @accel_group: the accelerator group to install an accelerator in
+ * @accel_path: path used for determining key and modifiers
+ * @closure: closure to be executed upon accelerator activation
+ *
+ * Installs an accelerator in this group, using an accelerator path
+ * to look up the appropriate key and modifiers (see
+ * gtk_accel_map_add_entry()). When @accel_group is being activated
+ * in response to a call to gtk_accel_groups_activate(), @closure will
+ * be invoked if the @accel_key and @accel_mods from
+ * gtk_accel_groups_activate() match the key and modifiers for the path.
+ *
+ * The signature used for the @closure is that of #GtkAccelGroupActivate.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore,
+ * if you pass a static string, you can save some memory by interning it
+ * first with g_intern_static_string().
+ */
+void
+gtk_accel_group_connect_by_path (GtkAccelGroup *accel_group,
+                                 const gchar   *accel_path,
+                                 GClosure      *closure)
+{
+  guint accel_key = 0;
+  GdkModifierType accel_mods = 0;
+  GtkAccelKey key;
+
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+  g_return_if_fail (closure != NULL);
+  g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+  if (closure->is_invalid)
+    return;
+
+  g_object_ref (accel_group);
+
+  if (gtk_accel_map_lookup_entry (accel_path, &key))
+    {
+      accel_key = gdk_keyval_to_lower (key.accel_key);
+      accel_mods = key.accel_mods;
+    }
+
+  quick_accel_add (accel_group, accel_key, accel_mods, GTK_ACCEL_VISIBLE, closure,
+                   g_quark_from_string (accel_path));
+
+  g_object_unref (accel_group);
+}
+
+/**
+ * gtk_accel_group_disconnect:
+ * @accel_group: the accelerator group to remove an accelerator from
+ * @closure: (allow-none): the closure to remove from this accelerator
+ *     group, or %NULL to remove all closures
+ *
+ * Removes an accelerator previously installed through
+ * gtk_accel_group_connect().
+ *
+ * Returns: %TRUE if the closure was found and got disconnected
+ */
+gboolean
+gtk_accel_group_disconnect (GtkAccelGroup *accel_group,
+                            GClosure      *closure)
+{
+  guint i;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+  for (i = 0; i < accel_group->priv->n_accels; i++)
+    if (accel_group->priv->priv_accels[i].closure == closure)
+      {
+        g_object_ref (accel_group);
+        quick_accel_remove (accel_group, i);
+        g_object_unref (accel_group);
+        return TRUE;
+      }
+  return FALSE;
+}
+
+/**
+ * gtk_accel_group_disconnect_key:
+ * @accel_group: the accelerator group to install an accelerator in
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ *
+ * Removes an accelerator previously installed through
+ * gtk_accel_group_connect().
+ *
+ * Returns: %TRUE if there was an accelerator which could be
+ *     removed, %FALSE otherwise
+ */
+gboolean
+gtk_accel_group_disconnect_key (GtkAccelGroup   *accel_group,
+                                guint            accel_key,
+                                GdkModifierType  accel_mods)
+{
+  GtkAccelGroupEntry *entries;
+  GSList *slist, *clist = NULL;
+  gboolean removed_one = FALSE;
+  guint n;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+  g_object_ref (accel_group);
+
+  accel_key = gdk_keyval_to_lower (accel_key);
+  entries = quick_accel_find (accel_group, accel_key, accel_mods, &n);
+  while (n--)
+    {
+      GClosure *closure = g_closure_ref (entries[n].closure);
+
+      clist = g_slist_prepend (clist, closure);
+    }
+
+  for (slist = clist; slist; slist = slist->next)
+    {
+      GClosure *closure = slist->data;
+
+      removed_one |= gtk_accel_group_disconnect (accel_group, closure);
+      g_closure_unref (closure);
+    }
+  g_slist_free (clist);
+
+  g_object_unref (accel_group);
+
+  return removed_one;
+}
+
+void
+_gtk_accel_group_reconnect (GtkAccelGroup *accel_group,
+                            GQuark         accel_path_quark)
+{
+  GSList *slist, *clist = NULL;
+  guint i;
+
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  g_object_ref (accel_group);
+
+  for (i = 0; i < accel_group->priv->n_accels; i++)
+    if (accel_group->priv->priv_accels[i].accel_path_quark == accel_path_quark)
+      {
+        GClosure *closure = g_closure_ref (accel_group->priv->priv_accels[i].closure);
+
+        clist = g_slist_prepend (clist, closure);
+      }
+
+  for (slist = clist; slist; slist = slist->next)
+    {
+      GClosure *closure = slist->data;
+
+      gtk_accel_group_disconnect (accel_group, closure);
+      gtk_accel_group_connect_by_path (accel_group, g_quark_to_string (accel_path_quark), closure);
+      g_closure_unref (closure);
+    }
+  g_slist_free (clist);
+
+  g_object_unref (accel_group);
+}
+
+GSList*
+_gtk_accel_group_get_accelerables (GtkAccelGroup *accel_group)
+{
+    g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+
+    return accel_group->priv->acceleratables;
+}
+
+/**
+ * gtk_accel_group_query:
+ * @accel_group: the accelerator group to query
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ * @n_entries: (out) (optional): location to return the number
+ *     of entries found, or %NULL
+ *
+ * Queries an accelerator group for all entries matching @accel_key
+ * and @accel_mods.
+ *
+ * Returns: (nullable) (transfer none) (array length=n_entries): an array of
+ *     @n_entries #GtkAccelGroupEntry elements, or %NULL. The array
+ *     is owned by GTK+ and must not be freed.
+ */
+GtkAccelGroupEntry*
+gtk_accel_group_query (GtkAccelGroup   *accel_group,
+                       guint            accel_key,
+                       GdkModifierType  accel_mods,
+                       guint           *n_entries)
+{
+  GtkAccelGroupEntry *entries;
+  guint n;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+
+  entries = quick_accel_find (accel_group, gdk_keyval_to_lower (accel_key), accel_mods, &n);
+
+  if (n_entries)
+    *n_entries = entries ? n : 0;
+
+  return entries;
+}
+
+/**
+ * gtk_accel_group_from_accel_closure:
+ * @closure: a #GClosure
+ *
+ * Finds the #GtkAccelGroup to which @closure is connected;
+ * see gtk_accel_group_connect().
+ *
+ * Returns: (nullable) (transfer none): the #GtkAccelGroup to which @closure
+ *     is connected, or %NULL
+ */
+GtkAccelGroup*
+gtk_accel_group_from_accel_closure (GClosure *closure)
+{
+  guint i;
+
+  g_return_val_if_fail (closure != NULL, NULL);
+
+  /* A few remarks on what we do here. in general, we need a way to
+   * reverse lookup accel_groups from closures that are being used in
+   * accel groups. this could be done e.g via a hashtable. it is however
+   * cheaper (memory wise) to just use the invalidation notifier on the
+   * closure itself (which we need to install anyway), that contains the
+   * accel group as data which, besides needing to peek a bit at closure
+   * internals, works just as good.
+   */
+  for (i = 0; i < G_CLOSURE_N_NOTIFIERS (closure); i++)
+    if (closure->notifiers[i].notify == accel_closure_invalidate)
+      return closure->notifiers[i].data;
+
+  return NULL;
+}
+
+/**
+ * gtk_accel_group_activate:
+ * @accel_group: a #GtkAccelGroup
+ * @accel_quark: the quark for the accelerator name
+ * @acceleratable: the #GObject, usually a #GtkWindow, on which
+ *    to activate the accelerator
+ * @accel_key: accelerator keyval from a key event
+ * @accel_mods: keyboard state mask from a key event
+ *
+ * Finds the first accelerator in @accel_group that matches
+ * @accel_key and @accel_mods, and activates it.
+ *
+ * Returns: %TRUE if an accelerator was activated and handled
+ *     this keypress
+ */
+gboolean
+gtk_accel_group_activate (GtkAccelGroup   *accel_group,
+                          GQuark           accel_quark,
+                          GObject         *acceleratable,
+                          guint            accel_key,
+                          GdkModifierType  accel_mods)
+{
+  gboolean was_handled;
+
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+  g_return_val_if_fail (G_IS_OBJECT (acceleratable), FALSE);
+
+  was_handled = FALSE;
+  g_signal_emit (accel_group, signal_accel_activate, accel_quark,
+                 acceleratable, accel_key, accel_mods, &was_handled);
+
+  return was_handled;
+}
+
+/**
+ * gtk_accel_groups_activate:
+ * @object: the #GObject, usually a #GtkWindow, on which
+ *     to activate the accelerator
+ * @accel_key: accelerator keyval from a key event
+ * @accel_mods: keyboard state mask from a key event
+ *
+ * Finds the first accelerator in any #GtkAccelGroup attached
+ * to @object that matches @accel_key and @accel_mods, and
+ * activates that accelerator.
+ *
+ * Returns: %TRUE if an accelerator was activated and handled
+ *     this keypress
+ */
+gboolean
+gtk_accel_groups_activate (GObject         *object,
+                           guint            accel_key,
+                           GdkModifierType  accel_mods)
+{
+  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+  if (gtk_accelerator_valid (accel_key, accel_mods))
+    {
+      gchar *accel_name;
+      GQuark accel_quark;
+      GSList *slist;
+
+      accel_name = gtk_accelerator_name (accel_key, (accel_mods & gtk_accelerator_get_default_mod_mask ()));
+      accel_quark = g_quark_from_string (accel_name);
+      g_free (accel_name);
+
+      for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next)
+        if (gtk_accel_group_activate (slist->data, accel_quark, object, accel_key, accel_mods))
+          return TRUE;
+    }
+
+  return FALSE;
+}
+
 /**
  * gtk_accelerator_valid:
  * @keyval: a GDK keyval
@@ -204,6 +1087,20 @@ is_control (const gchar *string)
           (string[8] == '>'));
 }
 
+static inline gboolean
+is_release (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'r' || string[1] == 'R') &&
+          (string[2] == 'e' || string[2] == 'E') &&
+          (string[3] == 'l' || string[3] == 'L') &&
+          (string[4] == 'e' || string[4] == 'E') &&
+          (string[5] == 'a' || string[5] == 'A') &&
+          (string[6] == 's' || string[6] == 'S') &&
+          (string[7] == 'e' || string[7] == 'E') &&
+          (string[8] == '>'));
+}
+
 static inline gboolean
 is_meta (const gchar *string)
 {
@@ -265,7 +1162,6 @@ is_keycode (const gchar *string)
 /**
  * gtk_accelerator_parse_with_keycode:
  * @accelerator: string representing an accelerator
- * @display: (allow-none): the #GdkDisplay to look up @accelerator_codes in
  * @accelerator_key: (out) (allow-none): return location for accelerator
  *     keyval, or %NULL
  * @accelerator_codes: (out) (array zero-terminated=1) (transfer full) (allow-none):
@@ -286,12 +1182,9 @@ is_keycode (const gchar *string)
  *
  * If the parse fails, @accelerator_key, @accelerator_mods and
  * @accelerator_codes will be set to 0 (zero).
- *
- * Returns: %TRUE if parsing succeeded
  */
-gboolean
+void
 gtk_accelerator_parse_with_keycode (const gchar     *accelerator,
-                                    GdkDisplay      *display,
                                     guint           *accelerator_key,
                                     guint          **accelerator_codes,
                                     GdkModifierType *accelerator_mods)
@@ -307,8 +1200,7 @@ gtk_accelerator_parse_with_keycode (const gchar     *accelerator,
     *accelerator_mods = 0;
   if (accelerator_codes)
     *accelerator_codes = NULL;
-
-  g_return_val_if_fail (accelerator != NULL, FALSE);
+  g_return_if_fail (accelerator != NULL);
 
   error = FALSE;
   keyval = 0;
@@ -318,7 +1210,13 @@ gtk_accelerator_parse_with_keycode (const gchar     *accelerator,
     {
       if (*accelerator == '<')
         {
-          if (len >= 9 && is_primary (accelerator))
+          if (len >= 9 && is_release (accelerator))
+            {
+              accelerator += 9;
+              len -= 9;
+              mods |= GDK_RELEASE_MASK;
+            }
+          else if (len >= 9 && is_primary (accelerator))
             {
               accelerator += 9;
               len -= 9;
@@ -455,7 +1353,7 @@ gtk_accelerator_parse_with_keycode (const gchar     *accelerator,
 
           if (keyval && accelerator_codes != NULL)
             {
-              GdkKeymap *keymap = gdk_display_get_keymap (display ? display : gdk_display_get_default ());
+              GdkKeymap *keymap = gdk_display_get_keymap (gdk_display_get_default ());
               GdkKeymapKey *keys;
               gint n_keys, i, j;
 
@@ -518,8 +1416,6 @@ out:
     *accelerator_key = gdk_keyval_to_lower (keyval);
   if (accelerator_mods)
     *accelerator_mods = mods;
-
-  return !error;
 }
 
 /**
@@ -543,12 +1439,12 @@ out:
  * If the parse fails, @accelerator_key and @accelerator_mods will
  * be set to 0 (zero).
  */
-gboolean
+void
 gtk_accelerator_parse (const gchar     *accelerator,
                        guint           *accelerator_key,
                        GdkModifierType *accelerator_mods)
 {
-  return gtk_accelerator_parse_with_keycode (accelerator, NULL, accelerator_key, NULL, accelerator_mods);
+  gtk_accelerator_parse_with_keycode (accelerator, accelerator_key, NULL, accelerator_mods);
 }
 
 /**
@@ -609,6 +1505,7 @@ gchar*
 gtk_accelerator_name (guint           accelerator_key,
                       GdkModifierType accelerator_mods)
 {
+  static const gchar text_release[] = "<Release>";
   static const gchar text_primary[] = "<Primary>";
   static const gchar text_shift[] = "<Shift>";
   static const gchar text_control[] = "<Control>";
@@ -633,6 +1530,8 @@ gtk_accelerator_name (guint           accelerator_key,
 
   saved_mods = accelerator_mods;
   l = 0;
+  if (accelerator_mods & GDK_RELEASE_MASK)
+    l += sizeof (text_release) - 1;
   if (accelerator_mods & _gtk_get_primary_accel_mod ())
     {
       l += sizeof (text_primary) - 1;
@@ -665,6 +1564,11 @@ gtk_accelerator_name (guint           accelerator_key,
   accelerator_mods = saved_mods;
   l = 0;
   accelerator[l] = 0;
+  if (accelerator_mods & GDK_RELEASE_MASK)
+    {
+      strcpy (accelerator + l, text_release);
+      l += sizeof (text_release) - 1;
+    }
   if (accelerator_mods & _gtk_get_primary_accel_mod ())
     {
       strcpy (accelerator + l, text_primary);
@@ -768,131 +1672,6 @@ gtk_accelerator_get_label_with_keycode (GdkDisplay      *display,
   return gtk_label;
 }
 
-/* Underscores in key names are better displayed as spaces
- * E.g., Page_Up should be “Page Up”.
- *
- * Some keynames also have prefixes that are not suitable
- * for display, e.g XF86AudioMute, so strip those out, too.
- *
- * This function is only called on untranslated keynames,
- * so no need to be UTF-8 safe.
- */
-static void
-append_without_underscores (GString    *s,
-                            const char *str)
-{
-  const char *p;
-
-  if (g_str_has_prefix (str, "XF86"))
-    p = str + 4;
-  else if (g_str_has_prefix (str, "ISO_"))
-    p = str + 4;
-  else
-    p = str;
-
-  for ( ; *p; p++)
-    {
-      if (*p == '_')
-        g_string_append_c (s, ' ');
-      else
-        g_string_append_c (s, *p);
-    }
-}
-
-/* On Mac, if the key has symbolic representation (e.g. arrow keys),
- * append it to gstring and return TRUE; otherwise return FALSE.
- * See http://docs.info.apple.com/article.html?path=Mac/10.5/en/cdb_symbs.html
- * for the list of special keys. */
-static gboolean
-append_keyval_symbol (guint    accelerator_key,
-                      GString *gstring)
-{
-#ifdef GDK_WINDOWING_QUARTZ
-  switch (accelerator_key)
-  {
-  case GDK_KEY_Return:
-    /* U+21A9 LEFTWARDS ARROW WITH HOOK */
-    g_string_append (gstring, "\xe2\x86\xa9");
-    return TRUE;
-
-  case GDK_KEY_ISO_Enter:
-    /* U+2324 UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS */
-    g_string_append (gstring, "\xe2\x8c\xa4");
-    return TRUE;
-
-  case GDK_KEY_Left:
-    /* U+2190 LEFTWARDS ARROW */
-    g_string_append (gstring, "\xe2\x86\x90");
-    return TRUE;
-
-  case GDK_KEY_Up:
-    /* U+2191 UPWARDS ARROW */
-    g_string_append (gstring, "\xe2\x86\x91");
-    return TRUE;
-
-  case GDK_KEY_Right:
-    /* U+2192 RIGHTWARDS ARROW */
-    g_string_append (gstring, "\xe2\x86\x92");
-    return TRUE;
-
-  case GDK_KEY_Down:
-    /* U+2193 DOWNWARDS ARROW */
-    g_string_append (gstring, "\xe2\x86\x93");
-    return TRUE;
-
-  case GDK_KEY_Page_Up:
-    /* U+21DE UPWARDS ARROW WITH DOUBLE STROKE */
-    g_string_append (gstring, "\xe2\x87\x9e");
-    return TRUE;
-
-  case GDK_KEY_Page_Down:
-    /* U+21DF DOWNWARDS ARROW WITH DOUBLE STROKE */
-    g_string_append (gstring, "\xe2\x87\x9f");
-    return TRUE;
-
-  case GDK_KEY_Home:
-    /* U+2196 NORTH WEST ARROW */
-    g_string_append (gstring, "\xe2\x86\x96");
-    return TRUE;
-
-  case GDK_KEY_End:
-    /* U+2198 SOUTH EAST ARROW */
-    g_string_append (gstring, "\xe2\x86\x98");
-    return TRUE;
-
-  case GDK_KEY_Escape:
-    /* U+238B BROKEN CIRCLE WITH NORTHWEST ARROW */
-    g_string_append (gstring, "\xe2\x8e\x8b");
-    return TRUE;
-
-  case GDK_KEY_BackSpace:
-    /* U+232B ERASE TO THE LEFT */
-    g_string_append (gstring, "\xe2\x8c\xab");
-    return TRUE;
-
-  case GDK_KEY_Delete:
-    /* U+2326 ERASE TO THE RIGHT */
-    g_string_append (gstring, "\xe2\x8c\xa6");
-    return TRUE;
-
-  default:
-    return FALSE;
-  }
-#else /* !GDK_WINDOWING_QUARTZ */
-  return FALSE;
-#endif
-}
-
-static void
-append_separator (GString *string)
-{
-#ifndef GDK_WINDOWING_QUARTZ
-  g_string_append (string, "+");
-#else
-  /* no separator on quartz */
-#endif
-}
-
 /**
  * gtk_accelerator_get_label:
  * @accelerator_key: accelerator keyval
@@ -907,202 +1686,16 @@ gchar*
 gtk_accelerator_get_label (guint           accelerator_key,
                            GdkModifierType accelerator_mods)
 {
-  GString *gstring;
-
-  gstring = g_string_new (NULL);
-
-  gtk_accelerator_print_label (gstring, accelerator_key, accelerator_mods);
-
-  return g_string_free (gstring, FALSE);
-}
-
-void
-gtk_accelerator_print_label (GString        *gstring,
-                             guint           accelerator_key,
-                             GdkModifierType accelerator_mods)
-{
-  gboolean seen_mod = FALSE;
-  gunichar ch;
-
-  if (accelerator_mods & GDK_SHIFT_MASK)
-    {
-#ifndef GDK_WINDOWING_QUARTZ
-      /* This is the text that should appear next to menu accelerators
-       * that use the shift key. If the text on this key isn't typically
-       * translated on keyboards used for your language, don't translate
-       * this.
-       */
-      g_string_append (gstring, C_("keyboard label", "Shift"));
-#else
-      /* U+21E7 UPWARDS WHITE ARROW */
-      g_string_append (gstring, "\xe2\x87\xa7");
-#endif
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_CONTROL_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-#ifndef GDK_WINDOWING_QUARTZ
-      /* This is the text that should appear next to menu accelerators
-       * that use the control key. If the text on this key isn't typically
-       * translated on keyboards used for your language, don't translate
-       * this.
-       */
-      g_string_append (gstring, C_("keyboard label", "Ctrl"));
-#else
-      /* U+2303 UP ARROWHEAD */
-      g_string_append (gstring, "\xe2\x8c\x83");
-#endif
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_MOD1_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-#ifndef GDK_WINDOWING_QUARTZ
-      /* This is the text that should appear next to menu accelerators
-       * that use the alt key. If the text on this key isn't typically
-       * translated on keyboards used for your language, don't translate
-       * this.
-       */
-      g_string_append (gstring, C_("keyboard label", "Alt"));
-#else
-      /* U+2325 OPTION KEY */
-      g_string_append (gstring, "\xe2\x8c\xa5");
-#endif
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_MOD2_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-      g_string_append (gstring, "Mod2");
-      seen_mod = TRUE;
-    }
+  GtkAccelLabelClass *klass;
+  gchar *label;
 
-  if (accelerator_mods & GDK_MOD3_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
+  klass = g_type_class_ref (GTK_TYPE_ACCEL_LABEL);
+  label = _gtk_accel_label_class_get_accelerator_label (klass,
+                                                        accelerator_key,
+                                                        accelerator_mods);
+  g_type_class_unref (klass); /* klass is kept alive since gtk uses static types */
 
-      g_string_append (gstring, "Mod3");
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_MOD4_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-      g_string_append (gstring, "Mod4");
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_MOD5_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-      g_string_append (gstring, "Mod5");
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_SUPER_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-      /* This is the text that should appear next to menu accelerators
-       * that use the super key. If the text on this key isn't typically
-       * translated on keyboards used for your language, don't translate
-       * this.
-       */
-      g_string_append (gstring, C_("keyboard label", "Super"));
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_HYPER_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-      /* This is the text that should appear next to menu accelerators
-       * that use the hyper key. If the text on this key isn't typically
-       * translated on keyboards used for your language, don't translate
-       * this.
-       */
-      g_string_append (gstring, C_("keyboard label", "Hyper"));
-      seen_mod = TRUE;
-    }
-
-  if (accelerator_mods & GDK_META_MASK)
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-#ifndef GDK_WINDOWING_QUARTZ
-      /* This is the text that should appear next to menu accelerators
-       * that use the meta key. If the text on this key isn't typically
-       * translated on keyboards used for your language, don't translate
-       * this.
-       */
-      g_string_append (gstring, C_("keyboard label", "Meta"));
-#else
-      /* Command key symbol U+2318 PLACE OF INTEREST SIGN */
-      g_string_append (gstring, "\xe2\x8c\x98");
-#endif
-      seen_mod = TRUE;
-    }
-
-  ch = gdk_keyval_to_unicode (accelerator_key);
-  if (ch && (ch == ' ' || g_unichar_isgraph (ch)))
-    {
-      if (seen_mod)
-        append_separator (gstring);
-
-      switch (ch)
-       {
-       case ' ':
-         g_string_append (gstring, C_("keyboard label", "Space"));
-         break;
-       case '\\':
-         g_string_append (gstring, C_("keyboard label", "Backslash"));
-         break;
-       default:
-         g_string_append_unichar (gstring, g_unichar_toupper (ch));
-         break;
-       }
-    }
-  else if (!append_keyval_symbol (accelerator_key, gstring))
-    {
-      const char *tmp;
-
-      tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
-      if (tmp != NULL)
-       {
-          if (seen_mod)
-            append_separator (gstring);
-
-         if (tmp[0] != 0 && tmp[1] == 0)
-           g_string_append_c (gstring, g_ascii_toupper (tmp[0]));
-         else
-           {
-             const char *str;
-              str = g_dpgettext2 (GETTEXT_PACKAGE, "keyboard label", tmp);
-             if (str == tmp)
-                append_without_underscores (gstring, tmp);
-             else
-               g_string_append (gstring, str);
-           }
-       }
-    }
+  return label;
 }
 
 /**
index 69d0a3f227aee39e2838f022a718d7a1ceae2b12..bdb4d298885d6cc7f8c4994713b87c6cb81a064b 100644 (file)
 G_BEGIN_DECLS
 
 
+/* --- type macros --- */
+#define GTK_TYPE_ACCEL_GROUP              (gtk_accel_group_get_type ())
+#define GTK_ACCEL_GROUP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_ACCEL_GROUP, GtkAccelGroup))
+#define GTK_ACCEL_GROUP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
+#define GTK_IS_ACCEL_GROUP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ACCEL_GROUP))
+#define GTK_IS_ACCEL_GROUP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ACCEL_GROUP))
+#define GTK_ACCEL_GROUP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
+
+
+/* --- accel flags --- */
+/**
+ * GtkAccelFlags:
+ * @GTK_ACCEL_VISIBLE: Accelerator is visible
+ * @GTK_ACCEL_LOCKED: Accelerator not removable
+ * @GTK_ACCEL_MASK: Mask
+ *
+ * Accelerator flags used with gtk_accel_group_connect().
+ */
+typedef enum
+{
+  GTK_ACCEL_VISIBLE        = 1 << 0,
+  GTK_ACCEL_LOCKED         = 1 << 1,
+  GTK_ACCEL_MASK           = 0x07
+} GtkAccelFlags;
+
+
+/* --- typedefs & structures --- */
+typedef struct _GtkAccelGroup            GtkAccelGroup;
+typedef struct _GtkAccelGroupClass        GtkAccelGroupClass;
+typedef struct _GtkAccelGroupPrivate      GtkAccelGroupPrivate;
+typedef struct _GtkAccelKey               GtkAccelKey;
+typedef struct _GtkAccelGroupEntry        GtkAccelGroupEntry;
+typedef gboolean (*GtkAccelGroupActivate) (GtkAccelGroup  *accel_group,
+                                          GObject        *acceleratable,
+                                          guint           keyval,
+                                          GdkModifierType modifier);
+
+/**
+ * GtkAccelGroupFindFunc:
+ * @key: 
+ * @closure: 
+ * @data: (closure):
+ */
+typedef gboolean (*GtkAccelGroupFindFunc) (GtkAccelKey    *key,
+                                          GClosure       *closure,
+                                          gpointer        data);
+
+/**
+ * GtkAccelGroup:
+ * 
+ * An object representing and maintaining a group of accelerators.
+ */
+struct _GtkAccelGroup
+{
+  GObject               parent;
+  GtkAccelGroupPrivate *priv;
+};
+
+/**
+ * GtkAccelGroupClass:
+ * @parent_class: The parent class.
+ * @accel_changed: Signal emitted when an entry is added to or removed
+ *    from the accel group.
+ */
+struct _GtkAccelGroupClass
+{
+  GObjectClass parent_class;
+
+  /*< public >*/
+
+  void (*accel_changed)        (GtkAccelGroup  *accel_group,
+                                guint           keyval,
+                                GdkModifierType modifier,
+                                GClosure       *accel_closure);
+
+  /*< private >*/
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+/**
+ * GtkAccelKey:
+ * @accel_key: The accelerator keyval
+ * @accel_mods:The accelerator modifiers
+ * @accel_flags: The accelerator flags
+ */
+struct _GtkAccelKey
+{
+  guint           accel_key;
+  GdkModifierType accel_mods;
+  guint           accel_flags : 16;
+};
+
+
+/* -- Accelerator Groups --- */
+GDK_AVAILABLE_IN_ALL
+GType          gtk_accel_group_get_type           (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkAccelGroup* gtk_accel_group_new               (void);
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_accel_group_get_is_locked      (GtkAccelGroup  *accel_group);
+GDK_AVAILABLE_IN_ALL
+GdkModifierType 
+               gtk_accel_group_get_modifier_mask  (GtkAccelGroup  *accel_group);
+GDK_AVAILABLE_IN_ALL
+void          gtk_accel_group_lock               (GtkAccelGroup  *accel_group);
+GDK_AVAILABLE_IN_ALL
+void          gtk_accel_group_unlock             (GtkAccelGroup  *accel_group);
+GDK_AVAILABLE_IN_ALL
+void          gtk_accel_group_connect            (GtkAccelGroup  *accel_group,
+                                                  guint           accel_key,
+                                                  GdkModifierType accel_mods,
+                                                  GtkAccelFlags   accel_flags,
+                                                  GClosure       *closure);
+GDK_AVAILABLE_IN_ALL
+void           gtk_accel_group_connect_by_path    (GtkAccelGroup  *accel_group,
+                                                  const gchar    *accel_path,
+                                                  GClosure       *closure);
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_accel_group_disconnect        (GtkAccelGroup  *accel_group,
+                                                  GClosure       *closure);
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_accel_group_disconnect_key    (GtkAccelGroup  *accel_group,
+                                                  guint           accel_key,
+                                                  GdkModifierType accel_mods);
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_accel_group_activate           (GtkAccelGroup   *accel_group,
+                                                   GQuark         accel_quark,
+                                                   GObject       *acceleratable,
+                                                   guint          accel_key,
+                                                   GdkModifierType accel_mods);
+
+
+/* --- GtkActivatable glue --- */
+void           _gtk_accel_group_attach         (GtkAccelGroup  *accel_group,
+                                                GObject        *object);
+void           _gtk_accel_group_detach         (GtkAccelGroup  *accel_group,
+                                                GObject        *object);
+GDK_AVAILABLE_IN_ALL
+gboolean        gtk_accel_groups_activate              (GObject        *object,
+                                                guint           accel_key,
+                                                GdkModifierType accel_mods);
+GDK_AVAILABLE_IN_ALL
+GSList*                gtk_accel_groups_from_object    (GObject        *object);
+GDK_AVAILABLE_IN_ALL
+GtkAccelKey*   gtk_accel_group_find            (GtkAccelGroup        *accel_group,
+                                                GtkAccelGroupFindFunc find_func,
+                                                gpointer              data);
+GDK_AVAILABLE_IN_ALL
+GtkAccelGroup* gtk_accel_group_from_accel_closure (GClosure    *closure);
+
+
 /* --- Accelerators--- */
 GDK_AVAILABLE_IN_ALL
 gboolean gtk_accelerator_valid               (guint            keyval,
                                               GdkModifierType  modifiers) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
-gboolean gtk_accelerator_parse               (const gchar     *accelerator,
+void    gtk_accelerator_parse                (const gchar     *accelerator,
                                               guint           *accelerator_key,
                                               GdkModifierType *accelerator_mods);
 GDK_AVAILABLE_IN_ALL
-gboolean gtk_accelerator_parse_with_keycode   (const gchar     *accelerator,
-                                               GdkDisplay      *display,
+void gtk_accelerator_parse_with_keycode       (const gchar     *accelerator,
                                                guint           *accelerator_key,
                                                guint          **accelerator_codes,
                                                GdkModifierType *accelerator_mods);
@@ -72,6 +227,21 @@ GDK_AVAILABLE_IN_ALL
 GdkModifierType
         gtk_accelerator_get_default_mod_mask (void);
 
+GDK_AVAILABLE_IN_ALL
+GtkAccelGroupEntry*    gtk_accel_group_query   (GtkAccelGroup  *accel_group,
+                                                guint           accel_key,
+                                                GdkModifierType accel_mods,
+                                                guint          *n_entries);
+
+struct _GtkAccelGroupEntry
+{
+  GtkAccelKey  key;
+  GClosure    *closure;
+  GQuark       accel_path_quark;
+};
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkAccelGroup, g_object_unref)
+
 G_END_DECLS
 
 #endif /* __GTK_ACCEL_GROUP_H__ */
index c5b4daef558bffd742af9da23913b1fc24049401..15da43ae2b30b4f3c8710ff20566da546efa7868 100644 (file)
 
 G_BEGIN_DECLS
 
-void    gtk_accelerator_print_label             (GString                *gstring,
-                                                 guint                   accelerator_key,
-                                                 GdkModifierType         accelerator_mods);
+struct _GtkAccelGroupPrivate
+{
+  guint               lock_count;
+  GdkModifierType     modifier_mask;
+  GSList             *acceleratables;
+  guint               n_accels;
+  GtkAccelGroupEntry *priv_accels;
+};
+
+void   _gtk_accel_group_reconnect        (GtkAccelGroup *accel_group,
+                                           GQuark         accel_path_quark);
+GSList* _gtk_accel_group_get_accelerables (GtkAccelGroup *accel_group);
+
 G_END_DECLS
 
 #endif /* __GTK_ACCEL_GROUP_PRIVATE_H__ */
index 4fabce26a5556af324fdcd5de64ce038e7b1796e..75ee16bc8cb39827be8b0fa983d544c50b5cede9 100644 (file)
@@ -29,7 +29,9 @@
 #include <string.h>
 
 #include "gtklabel.h"
+#include "gtkaccellabel.h"
 #include "gtkaccellabelprivate.h"
+#include "gtkaccelmap.h"
 #include "gtkintl.h"
 #include "gtkmain.h"
 #include "gtkprivate.h"
@@ -68,6 +70,7 @@
  * set (see #GtkAccelFlags).
  * A #GtkAccelLabel can display multiple accelerators and even signal names,
  * though it is almost always used to display just one accelerator key.
+ * ]|
  *
  * # CSS nodes
  *
@@ -83,6 +86,8 @@
 
 enum {
   PROP_0,
+  PROP_ACCEL_CLOSURE,
+  PROP_ACCEL_WIDGET,
   PROP_LABEL,
   PROP_USE_UNDERLINE,
   LAST_PROP
@@ -109,6 +114,10 @@ struct _GtkAccelLabelPrivate
   GtkWidget     *text_label;
   GtkWidget     *accel_label;
 
+  GtkWidget     *accel_widget;       /* done */
+  GClosure      *accel_closure;      /* has set function */
+  GtkAccelGroup *accel_group;        /* set by set_accel_closure() */
+
   guint           accel_key;         /* manual accel key specification if != 0 */
   GdkModifierType accel_mods;
 };
@@ -123,6 +132,7 @@ static void         gtk_accel_label_get_property (GObject            *object,
                                                  guint               prop_id,
                                                  GValue             *value,
                                                  GParamSpec         *pspec);
+static void         gtk_accel_label_destroy      (GtkWidget          *widget);
 static void         gtk_accel_label_finalize     (GObject            *object);
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_WIDGET)
@@ -137,8 +147,56 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
   gobject_class->set_property = gtk_accel_label_set_property;
   gobject_class->get_property = gtk_accel_label_get_property;
 
+  widget_class->destroy = gtk_accel_label_destroy;
+
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_ACCEL_LABEL);
 
+#ifndef GDK_WINDOWING_QUARTZ
+  /* This is the text that should appear next to menu accelerators
+   * that use the shift key. If the text on this key isn't typically
+   * translated on keyboards used for your language, don't translate
+   * this.
+   */
+  class->mod_name_shift = g_strdup (C_("keyboard label", "Shift"));
+  /* This is the text that should appear next to menu accelerators
+   * that use the control key. If the text on this key isn't typically
+   * translated on keyboards used for your language, don't translate
+   * this.
+   */
+  class->mod_name_control = g_strdup (C_("keyboard label", "Ctrl"));
+  /* This is the text that should appear next to menu accelerators
+   * that use the alt key. If the text on this key isn't typically
+   * translated on keyboards used for your language, don't translate
+   * this.
+   */
+  class->mod_name_alt = g_strdup (C_("keyboard label", "Alt"));
+  class->mod_separator = g_strdup ("+");
+#else /* GDK_WINDOWING_QUARTZ */
+
+  /* U+21E7 UPWARDS WHITE ARROW */
+  class->mod_name_shift = g_strdup ("\xe2\x87\xa7");
+  /* U+2303 UP ARROWHEAD */
+  class->mod_name_control = g_strdup ("\xe2\x8c\x83");
+  /* U+2325 OPTION KEY */
+  class->mod_name_alt = g_strdup ("\xe2\x8c\xa5");
+  class->mod_separator = g_strdup ("");
+
+#endif /* GDK_WINDOWING_QUARTZ */
+
+  props[PROP_ACCEL_CLOSURE] =
+    g_param_spec_boxed ("accel-closure",
+                        P_("Accelerator Closure"),
+                        P_("The closure to be monitored for accelerator changes"),
+                        G_TYPE_CLOSURE,
+                        GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  props[PROP_ACCEL_WIDGET] =
+    g_param_spec_object ("accel-widget",
+                         P_("Accelerator Widget"),
+                         P_("The widget to be monitored for accelerator changes"),
+                         GTK_TYPE_WIDGET,
+                         GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
   props[PROP_LABEL] =
     g_param_spec_string ("label",
                          P_("Label"),
@@ -171,6 +229,12 @@ gtk_accel_label_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_ACCEL_CLOSURE:
+      gtk_accel_label_set_accel_closure (accel_label, g_value_get_boxed (value));
+      break;
+    case PROP_ACCEL_WIDGET:
+      gtk_accel_label_set_accel_widget (accel_label, g_value_get_object (value));
+      break;
     case PROP_LABEL:
       gtk_accel_label_set_label (accel_label, g_value_get_string (value));
       break;
@@ -190,9 +254,16 @@ gtk_accel_label_get_property (GObject    *object,
                              GParamSpec *pspec)
 {
   GtkAccelLabel  *accel_label = GTK_ACCEL_LABEL (object);
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
 
   switch (prop_id)
     {
+    case PROP_ACCEL_CLOSURE:
+      g_value_set_boxed (value, priv->accel_closure);
+      break;
+    case PROP_ACCEL_WIDGET:
+      g_value_set_object (value, priv->accel_widget);
+      break;
     case PROP_LABEL:
       g_value_set_string (value, gtk_accel_label_get_label (accel_label));
       break;
@@ -210,6 +281,10 @@ gtk_accel_label_init (GtkAccelLabel *accel_label)
 {
   GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
 
+  priv->accel_widget = NULL;
+  priv->accel_closure = NULL;
+  priv->accel_group = NULL;
+
   priv->text_label = gtk_label_new ("");
   gtk_widget_set_hexpand (priv->text_label, TRUE);
   gtk_label_set_xalign (GTK_LABEL (priv->text_label), 0.0f);
@@ -242,6 +317,17 @@ gtk_accel_label_new (const gchar *string)
   return GTK_WIDGET (accel_label);
 }
 
+static void
+gtk_accel_label_destroy (GtkWidget *widget)
+{
+  GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
+
+  gtk_accel_label_set_accel_widget (accel_label, NULL);
+  gtk_accel_label_set_accel_closure (accel_label, NULL);
+
+  GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->destroy (widget);
+}
+
 static void
 gtk_accel_label_finalize (GObject *object)
 {
@@ -254,6 +340,26 @@ gtk_accel_label_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_accel_label_parent_class)->finalize (object);
 }
 
+/**
+ * gtk_accel_label_get_accel_widget:
+ * @accel_label: a #GtkAccelLabel
+ *
+ * Fetches the widget monitored by this accelerator label. See
+ * gtk_accel_label_set_accel_widget().
+ *
+ * Returns: (nullable) (transfer none): the widget monitored by @accel_label,
+ * or %NULL if it is not monitoring a widget.
+ **/
+GtkWidget *
+gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
+
+  return priv->accel_widget;
+}
+
 /**
  * gtk_accel_label_get_accel_width:
  * @accel_label: a #GtkAccelLabel.
@@ -278,6 +384,463 @@ gtk_accel_label_get_accel_width (GtkAccelLabel *accel_label)
   return min;
 }
 
+static void
+refetch_widget_accel_closure (GtkAccelLabel *accel_label)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+  GClosure *closure = NULL;
+  GList *clist, *list;
+
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+  g_return_if_fail (GTK_IS_WIDGET (priv->accel_widget));
+
+  clist = gtk_widget_list_accel_closures (priv->accel_widget);
+  for (list = clist; list; list = list->next)
+    {
+      /* we just take the first closure used */
+      closure = list->data;
+      break;
+    }
+
+  g_list_free (clist);
+  gtk_accel_label_set_accel_closure (accel_label, closure);
+}
+
+static void
+accel_widget_weak_ref_cb (GtkAccelLabel *accel_label,
+                          GtkWidget     *old_accel_widget)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+  g_return_if_fail (GTK_IS_WIDGET (priv->accel_widget));
+
+  g_signal_handlers_disconnect_by_func (priv->accel_widget,
+                                        refetch_widget_accel_closure,
+                                        accel_label);
+  priv->accel_widget = NULL;
+  g_object_notify_by_pspec (G_OBJECT (accel_label), props[PROP_ACCEL_WIDGET]);
+}
+
+/**
+ * gtk_accel_label_set_accel_widget:
+ * @accel_label: a #GtkAccelLabel
+ * @accel_widget: (nullable): the widget to be monitored, or %NULL
+ *
+ * Sets the widget to be monitored by this accelerator label. Passing %NULL for
+ * @accel_widget will dissociate @accel_label from its current widget, if any.
+ */
+void
+gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
+                                  GtkWidget     *accel_widget)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+
+  if (accel_widget)
+    g_return_if_fail (GTK_IS_WIDGET (accel_widget));
+
+  if (accel_widget != priv->accel_widget)
+    {
+      if (priv->accel_widget)
+        {
+          gtk_accel_label_set_accel_closure (accel_label, NULL);
+          g_signal_handlers_disconnect_by_func (priv->accel_widget,
+                                                refetch_widget_accel_closure,
+                                                accel_label);
+          g_object_weak_unref (G_OBJECT (priv->accel_widget),
+                               (GWeakNotify) accel_widget_weak_ref_cb, accel_label);
+        }
+
+      priv->accel_widget = accel_widget;
+
+      if (priv->accel_widget)
+        {
+          g_object_weak_ref (G_OBJECT (priv->accel_widget),
+                             (GWeakNotify) accel_widget_weak_ref_cb, accel_label);
+          g_signal_connect_object (priv->accel_widget, "accel-closures-changed",
+                                   G_CALLBACK (refetch_widget_accel_closure),
+                                   accel_label, G_CONNECT_SWAPPED);
+          refetch_widget_accel_closure (accel_label);
+        }
+
+      g_object_notify_by_pspec (G_OBJECT (accel_label), props[PROP_ACCEL_WIDGET]);
+    }
+}
+
+static void
+gtk_accel_label_reset (GtkAccelLabel *accel_label)
+{
+  gtk_accel_label_refetch (accel_label);
+}
+
+static void
+check_accel_changed (GtkAccelGroup  *accel_group,
+                    guint           keyval,
+                    GdkModifierType modifier,
+                    GClosure       *accel_closure,
+                    GtkAccelLabel  *accel_label)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  if (accel_closure == priv->accel_closure)
+    gtk_accel_label_reset (accel_label);
+}
+
+/**
+ * gtk_accel_label_set_accel_closure:
+ * @accel_label: a #GtkAccelLabel
+ * @accel_closure: (nullable): the closure to monitor for accelerator changes,
+ * or %NULL
+ *
+ * Sets the closure to be monitored by this accelerator label. The closure
+ * must be connected to an accelerator group; see gtk_accel_group_connect().
+ * Passing %NULL for @accel_closure will dissociate @accel_label from its
+ * current closure, if any.
+ **/
+void
+gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+                                   GClosure      *accel_closure)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+
+  if (accel_closure)
+    g_return_if_fail (gtk_accel_group_from_accel_closure (accel_closure) != NULL);
+
+  if (accel_closure != priv->accel_closure)
+    {
+      if (priv->accel_closure)
+        {
+          g_signal_handlers_disconnect_by_func (priv->accel_group,
+                                                check_accel_changed,
+                                                accel_label);
+          priv->accel_group = NULL;
+          g_closure_unref (priv->accel_closure);
+        }
+
+      priv->accel_closure = accel_closure;
+
+      if (priv->accel_closure)
+        {
+          g_closure_ref (priv->accel_closure);
+          priv->accel_group = gtk_accel_group_from_accel_closure (accel_closure);
+          g_signal_connect_object (priv->accel_group, "accel-changed", G_CALLBACK (check_accel_changed),
+                                   accel_label, 0);
+        }
+
+      gtk_accel_label_reset (accel_label);
+      g_object_notify_by_pspec (G_OBJECT (accel_label), props[PROP_ACCEL_CLOSURE]);
+    }
+}
+
+/**
+ * gtk_accel_label_get_accel_closure:
+ * @accel_label: a #GtkAccelLabel
+ *
+ * Fetches the closure monitored by this accelerator label. See
+ * gtk_accel_label_set_accel_closure().
+ *
+ * Returns: (nullable) (transfer none): the closure monitored by @accel_label,
+ *   or %NULL if it is not monitoring a closure.
+ */
+GClosure *
+gtk_accel_label_get_accel_closure (GtkAccelLabel *accel_label)
+{
+  GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
+
+  return priv->accel_closure;
+}
+
+static gboolean
+find_accel (GtkAccelKey *key,
+           GClosure    *closure,
+           gpointer     data)
+{
+  return data == (gpointer) closure;
+}
+
+/* Underscores in key names are better displayed as spaces
+ * E.g., Page_Up should be “Page Up”.
+ *
+ * Some keynames also have prefixes that are not suitable
+ * for display, e.g XF86AudioMute, so strip those out, too.
+ *
+ * This function is only called on untranslated keynames,
+ * so no need to be UTF-8 safe.
+ */
+static void
+append_without_underscores (GString    *s,
+                            const char *str)
+{
+  const char *p;
+
+  if (g_str_has_prefix (str, "XF86"))
+    p = str + 4;
+  else if (g_str_has_prefix (str, "ISO_"))
+    p = str + 4;
+  else
+    p = str;
+
+  for ( ; *p; p++)
+    {
+      if (*p == '_')
+        g_string_append_c (s, ' ');
+      else
+        g_string_append_c (s, *p);
+    }
+}
+
+/* On Mac, if the key has symbolic representation (e.g. arrow keys),
+ * append it to gstring and return TRUE; otherwise return FALSE.
+ * See http://docs.info.apple.com/article.html?path=Mac/10.5/en/cdb_symbs.html 
+ * for the list of special keys. */
+static gboolean
+append_keyval_symbol (guint    accelerator_key,
+                      GString *gstring)
+{
+#ifdef GDK_WINDOWING_QUARTZ
+  switch (accelerator_key)
+  {
+  case GDK_KEY_Return:
+    /* U+21A9 LEFTWARDS ARROW WITH HOOK */
+    g_string_append (gstring, "\xe2\x86\xa9");
+    return TRUE;
+
+  case GDK_KEY_ISO_Enter:
+    /* U+2324 UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS */
+    g_string_append (gstring, "\xe2\x8c\xa4");
+    return TRUE;
+
+  case GDK_KEY_Left:
+    /* U+2190 LEFTWARDS ARROW */
+    g_string_append (gstring, "\xe2\x86\x90");
+    return TRUE;
+
+  case GDK_KEY_Up:
+    /* U+2191 UPWARDS ARROW */
+    g_string_append (gstring, "\xe2\x86\x91");
+    return TRUE;
+
+  case GDK_KEY_Right:
+    /* U+2192 RIGHTWARDS ARROW */
+    g_string_append (gstring, "\xe2\x86\x92");
+    return TRUE;
+
+  case GDK_KEY_Down:
+    /* U+2193 DOWNWARDS ARROW */
+    g_string_append (gstring, "\xe2\x86\x93");
+    return TRUE;
+
+  case GDK_KEY_Page_Up:
+    /* U+21DE UPWARDS ARROW WITH DOUBLE STROKE */
+    g_string_append (gstring, "\xe2\x87\x9e");
+    return TRUE;
+
+  case GDK_KEY_Page_Down:
+    /* U+21DF DOWNWARDS ARROW WITH DOUBLE STROKE */
+    g_string_append (gstring, "\xe2\x87\x9f");
+    return TRUE;
+
+  case GDK_KEY_Home:
+    /* U+2196 NORTH WEST ARROW */
+    g_string_append (gstring, "\xe2\x86\x96");
+    return TRUE;
+
+  case GDK_KEY_End:
+    /* U+2198 SOUTH EAST ARROW */
+    g_string_append (gstring, "\xe2\x86\x98");
+    return TRUE;
+
+  case GDK_KEY_Escape:
+    /* U+238B BROKEN CIRCLE WITH NORTHWEST ARROW */
+    g_string_append (gstring, "\xe2\x8e\x8b");
+    return TRUE;
+
+  case GDK_KEY_BackSpace:
+    /* U+232B ERASE TO THE LEFT */
+    g_string_append (gstring, "\xe2\x8c\xab");
+    return TRUE;
+
+  case GDK_KEY_Delete:
+    /* U+2326 ERASE TO THE RIGHT */
+    g_string_append (gstring, "\xe2\x8c\xa6");
+    return TRUE;
+
+  default:
+    return FALSE;
+  }
+#else /* !GDK_WINDOWING_QUARTZ */
+  return FALSE;
+#endif
+}
+
+gchar *
+_gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass,
+                                             guint               accelerator_key,
+                                             GdkModifierType     accelerator_mods)
+{
+  GString *gstring;
+  gboolean seen_mod = FALSE;
+  gunichar ch;
+
+  gstring = g_string_sized_new (10); /* ~len('backspace') */
+
+  if (accelerator_mods & GDK_SHIFT_MASK)
+    {
+      g_string_append (gstring, klass->mod_name_shift);
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_CONTROL_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+      g_string_append (gstring, klass->mod_name_control);
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_MOD1_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+      g_string_append (gstring, klass->mod_name_alt);
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_MOD2_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      g_string_append (gstring, "Mod2");
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_MOD3_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      g_string_append (gstring, "Mod3");
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_MOD4_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      g_string_append (gstring, "Mod4");
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_MOD5_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      g_string_append (gstring, "Mod5");
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_SUPER_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      /* This is the text that should appear next to menu accelerators
+       * that use the super key. If the text on this key isn't typically
+       * translated on keyboards used for your language, don't translate
+       * this.
+       */
+      g_string_append (gstring, C_("keyboard label", "Super"));
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_HYPER_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      /* This is the text that should appear next to menu accelerators
+       * that use the hyper key. If the text on this key isn't typically
+       * translated on keyboards used for your language, don't translate
+       * this.
+       */
+      g_string_append (gstring, C_("keyboard label", "Hyper"));
+      seen_mod = TRUE;
+    }
+
+  if (accelerator_mods & GDK_META_MASK)
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+#ifndef GDK_WINDOWING_QUARTZ
+      /* This is the text that should appear next to menu accelerators
+       * that use the meta key. If the text on this key isn't typically
+       * translated on keyboards used for your language, don't translate
+       * this.
+       */
+      g_string_append (gstring, C_("keyboard label", "Meta"));
+#else
+      /* Command key symbol U+2318 PLACE OF INTEREST SIGN */
+      g_string_append (gstring, "\xe2\x8c\x98");
+#endif
+      seen_mod = TRUE;
+    }
+  
+  ch = gdk_keyval_to_unicode (accelerator_key);
+  if (ch && (ch == ' ' || g_unichar_isgraph (ch)))
+    {
+      if (seen_mod)
+        g_string_append (gstring, klass->mod_separator);
+
+      switch (ch)
+       {
+       case ' ':
+         g_string_append (gstring, C_("keyboard label", "Space"));
+         break;
+       case '\\':
+         g_string_append (gstring, C_("keyboard label", "Backslash"));
+         break;
+       default:
+         g_string_append_unichar (gstring, g_unichar_toupper (ch));
+         break;
+       }
+    }
+  else if (!append_keyval_symbol (accelerator_key, gstring))
+    {
+      const char *tmp;
+
+      tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
+      if (tmp != NULL)
+       {
+          if (seen_mod)
+            g_string_append (gstring, klass->mod_separator);
+
+         if (tmp[0] != 0 && tmp[1] == 0)
+           g_string_append_c (gstring, g_ascii_toupper (tmp[0]));
+         else
+           {
+             const gchar *str;
+              str = g_dpgettext2 (GETTEXT_PACKAGE, "keyboard label", tmp);
+             if (str == tmp)
+                append_without_underscores (gstring, tmp);
+             else
+               g_string_append (gstring, str);
+           }
+       }
+    }
+
+  return g_string_free (gstring, FALSE);
+}
+
 /**
  * gtk_accel_label_refetch:
  * @accel_label: a #GtkAccelLabel.
@@ -301,7 +864,7 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
                 "gtk-enable-accels", &enable_accels,
                 NULL);
 
-  if (enable_accels && priv->accel_key)
+  if (enable_accels && (priv->accel_closure || priv->accel_key))
     {
       gboolean have_accel = FALSE;
       guint accel_key;
@@ -315,9 +878,30 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
           have_accel = TRUE;
         }
 
+      /* If we don't have a hardcoded value, check the accel group */
+      if (!have_accel)
+        {
+          GtkAccelKey *key;
+
+          key = gtk_accel_group_find (priv->accel_group, find_accel, priv->accel_closure);
+
+          if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
+            {
+              accel_key = key->accel_key;
+              accel_mods = key->accel_mods;
+              have_accel = TRUE;
+            }
+        }
+
       /* If we found a key using either method, set it */
       if (have_accel)
-        accel_string = gtk_accelerator_get_label (accel_key, accel_mods);
+       {
+         GtkAccelLabelClass *klass;
+
+         klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
+          accel_string = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods);
+       }
+
       else
         /* Otherwise we have a closure with no key.  Show "-/-". */
         accel_string = g_strdup ("-/-");
@@ -359,7 +943,7 @@ gtk_accel_label_set_accel (GtkAccelLabel   *accel_label,
   priv->accel_key = accelerator_key;
   priv->accel_mods = accelerator_mods;
 
-  gtk_accel_label_refetch (accel_label);
+  gtk_accel_label_reset (accel_label);
 }
 
 /**
index 7177b79cebcf6c0fd01942ca7734124d5eae0e34..a5e63559f19027af3912d220badd38fa060ecfc5 100644 (file)
@@ -46,8 +46,18 @@ GType           gtk_accel_label_get_type          (void) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
 GtkWidget *gtk_accel_label_new              (const gchar   *string);
 GDK_AVAILABLE_IN_ALL
+GtkWidget *gtk_accel_label_get_accel_widget  (GtkAccelLabel *accel_label);
+GDK_AVAILABLE_IN_ALL
 guint     gtk_accel_label_get_accel_width   (GtkAccelLabel *accel_label);
 GDK_AVAILABLE_IN_ALL
+void      gtk_accel_label_set_accel_widget  (GtkAccelLabel *accel_label,
+                                             GtkWidget     *accel_widget);
+GDK_AVAILABLE_IN_ALL
+void       gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+                                              GClosure      *accel_closure);
+GDK_AVAILABLE_IN_ALL
+GClosure * gtk_accel_label_get_accel_closure (GtkAccelLabel *accel_label);
+GDK_AVAILABLE_IN_ALL
 gboolean   gtk_accel_label_refetch           (GtkAccelLabel *accel_label);
 GDK_AVAILABLE_IN_ALL
 void       gtk_accel_label_set_accel         (GtkAccelLabel   *accel_label,
diff --git a/gtk/gtkaccelmap.c b/gtk/gtkaccelmap.c
new file mode 100644 (file)
index 0000000..2c24d78
--- /dev/null
@@ -0,0 +1,1086 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkaccelmapprivate.h"
+#include "gtkaccelgroupprivate.h"
+
+#include "gtkmarshalers.h"
+#include "gtkwindowprivate.h"
+#include "gtkintl.h"
+
+#include <glib/gstdio.h>
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef G_OS_WIN32
+#include <io.h>
+#endif
+
+
+/**
+ * SECTION:gtkaccelmap
+ * @Short_description: Loadable keyboard accelerator specifications
+ * @Title: Accelerator Maps
+ * @See_also: #GtkAccelGroup, #GtkAccelKey, gtk_widget_set_accel_path(), gtk_menu_item_set_accel_path()
+ *
+ * Accelerator maps are used to define runtime configurable accelerators.
+ * Functions for manipulating them are are usually used by higher level
+ * convenience mechanisms and are thus considered
+ * “low-level”. You’ll want to use them if you’re manually creating menus that
+ * should have user-configurable accelerators.
+ *
+ * An accelerator is uniquely defined by:
+ * - accelerator path
+ * - accelerator key
+ * - accelerator modifiers
+ *
+ * The accelerator path must consist of
+ * “<WINDOWTYPE>/Category1/Category2/.../Action”, where WINDOWTYPE
+ * should be a unique application-specific identifier that corresponds
+ * to the kind of window the accelerator is being used in, e.g.
+ * “Gimp-Image”, “Abiword-Document” or “Gnumeric-Settings”.
+ * The “Category1/.../Action” portion is most appropriately chosen by
+ * the action the accelerator triggers, i.e. for accelerators on menu
+ * items, choose the item’s menu path, e.g. “File/Save As”,
+ * “Image/View/Zoom” or “Edit/Select All”. So a full valid accelerator
+ * path may look like: “<Gimp-Toolbox>/File/Dialogs/Tool Options...”.
+ *
+ * All accelerators are stored inside one global #GtkAccelMap that can
+ * be obtained using gtk_accel_map_get(). See
+ * [Monitoring changes][monitoring-changes] for additional
+ * details.
+ *
+ * # Manipulating accelerators
+ *
+ * New accelerators can be added using gtk_accel_map_add_entry().
+ * To search for specific accelerator, use gtk_accel_map_lookup_entry().
+ * Modifications of existing accelerators should be done using
+ * gtk_accel_map_change_entry().
+ *
+ * In order to avoid having some accelerators changed, they can be
+ * locked using gtk_accel_map_lock_path(). Unlocking is done using
+ * gtk_accel_map_unlock_path().
+ *
+ * # Saving and loading accelerator maps
+ *
+ * Accelerator maps can be saved to and loaded from some external
+ * resource. For simple saving and loading from file,
+ * gtk_accel_map_save() and gtk_accel_map_load() are provided.
+ * Saving and loading can also be done by providing file descriptor
+ * to gtk_accel_map_save_fd() and gtk_accel_map_load_fd().
+ *
+ * # Monitoring changes
+ *
+ * #GtkAccelMap object is only useful for monitoring changes of
+ * accelerators. By connecting to #GtkAccelMap::changed signal, one
+ * can monitor changes of all accelerators. It is also possible to
+ * monitor only single accelerator path by using it as a detail of
+ * the #GtkAccelMap::changed signal.
+ */
+
+
+/* --- structures --- */
+struct _GtkAccelMap
+{
+  GObject parent_instance;
+};
+
+struct _GtkAccelMapClass
+{
+  GObjectClass parent_class;
+};
+
+typedef struct {
+  const gchar *accel_path;
+  guint        accel_key;
+  guint        accel_mods;
+  guint               std_accel_key;
+  guint               std_accel_mods;
+  guint        changed    :  1;
+  guint        lock_count : 15;
+  GSList      *groups;
+} AccelEntry;
+
+/* --- signals --- */
+enum {
+  CHANGED,
+  LAST_SIGNAL
+};
+
+/* --- variables --- */
+
+static GHashTable  *accel_entry_ht = NULL;     /* accel_path -> AccelEntry */
+static GSList      *accel_filters = NULL;
+static gulong      accel_map_signals[LAST_SIGNAL] = { 0, };
+
+/* --- prototypes --- */
+static void do_accel_map_changed (AccelEntry *entry);
+
+/* --- functions --- */
+static guint
+accel_entry_hash (gconstpointer key)
+{
+  const AccelEntry *entry = key;
+
+  return g_str_hash (entry->accel_path);
+}
+
+static gboolean
+accel_entry_equal (gconstpointer key1,
+                  gconstpointer key2)
+{
+  const AccelEntry *entry1 = key1;
+  const AccelEntry *entry2 = key2;
+
+  return g_str_equal (entry1->accel_path, entry2->accel_path);
+}
+
+static int
+accel_entry_compare (gconstpointer a,
+                     gconstpointer b)
+{
+  const AccelEntry *entry1 = a;
+  const AccelEntry *entry2 = b;
+
+  return strcmp (entry1->accel_path, entry2->accel_path);
+}
+
+static inline AccelEntry*
+accel_path_lookup (const gchar *accel_path)
+{
+  AccelEntry ekey;
+
+  ekey.accel_path = accel_path;
+
+  /* safety NULL check for return_if_fail()s */
+  return accel_path ? g_hash_table_lookup (accel_entry_ht, &ekey) : NULL;
+}
+
+void
+_gtk_accel_map_init (void)
+{
+  if (accel_entry_ht == NULL)
+    accel_entry_ht = g_hash_table_new (accel_entry_hash, accel_entry_equal);
+}
+
+gboolean
+_gtk_accel_path_is_valid (const gchar *accel_path)
+{
+  gchar *p;
+
+  if (!accel_path || accel_path[0] != '<' ||
+      accel_path[1] == '<' || accel_path[1] == '>' || !accel_path[1])
+    return FALSE;
+  p = strchr (accel_path, '>');
+  if (!p || (p[1] != 0 && p[1] != '/'))
+    return FALSE;
+  return TRUE;
+}
+
+/**
+ * gtk_accel_map_add_entry:
+ * @accel_path: valid accelerator path
+ * @accel_key:  the accelerator key
+ * @accel_mods: the accelerator modifiers
+ *
+ * Registers a new accelerator with the global accelerator map.
+ * This function should only be called once per @accel_path
+ * with the canonical @accel_key and @accel_mods for this path.
+ * To change the accelerator during runtime programatically, use
+ * gtk_accel_map_change_entry().
+ * 
+ * Set @accel_key and @accel_mods to 0 to request a removal of
+ * the accelerator.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with 
+ * g_intern_static_string().
+ */
+void
+gtk_accel_map_add_entry (const gchar    *accel_path,
+                        guint           accel_key,
+                        GdkModifierType accel_mods)
+{
+  AccelEntry *entry;
+
+  g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+  if (!accel_key)
+    accel_mods = 0;
+  else
+    accel_mods &= gtk_accelerator_get_default_mod_mask ();
+
+  entry = accel_path_lookup (accel_path);
+  if (entry)
+    {
+      if (!entry->std_accel_key && !entry->std_accel_mods &&
+         (accel_key || accel_mods))
+       {
+         entry->std_accel_key = accel_key;
+         entry->std_accel_mods = accel_mods;
+         if (!entry->changed)
+           gtk_accel_map_change_entry (entry->accel_path, accel_key, accel_mods, TRUE);
+       }
+    }
+  else
+    {
+      entry = g_slice_new0 (AccelEntry);
+      entry->accel_path = g_intern_string (accel_path);
+      entry->std_accel_key = accel_key;
+      entry->std_accel_mods = accel_mods;
+      entry->accel_key = accel_key;
+      entry->accel_mods = accel_mods;
+      entry->changed = FALSE;
+      entry->lock_count = 0;
+      g_hash_table_insert (accel_entry_ht, entry, entry);
+
+      do_accel_map_changed (entry);
+    }
+}
+
+/**
+ * gtk_accel_map_lookup_entry:
+ * @accel_path: a valid accelerator path
+ * @key: (allow-none) (out): the accelerator key to be filled in (optional)
+ *
+ * Looks up the accelerator entry for @accel_path and fills in @key.
+ *
+ * Returns: %TRUE if @accel_path is known, %FALSE otherwise
+ */
+gboolean
+gtk_accel_map_lookup_entry (const gchar *accel_path,
+                           GtkAccelKey *key)
+{
+  AccelEntry *entry;
+
+  g_return_val_if_fail (_gtk_accel_path_is_valid (accel_path), FALSE);
+
+  entry = accel_path_lookup (accel_path);
+  if (entry && key)
+    {
+      key->accel_key = entry->accel_key;
+      key->accel_mods = entry->accel_mods;
+      key->accel_flags = 0;
+    }
+
+  return entry ? TRUE : FALSE;
+}
+
+static void
+hash2slist_foreach (gpointer  key,
+                   gpointer  value,
+                   gpointer  user_data)
+{
+  GSList **slist_p = user_data;
+
+  *slist_p = g_slist_prepend (*slist_p, value);
+}
+
+static GSList*
+g_hash_table_slist_values (GHashTable *hash_table)
+{
+  GSList *slist = NULL;
+
+  g_return_val_if_fail (hash_table != NULL, NULL);
+
+  g_hash_table_foreach (hash_table, hash2slist_foreach, &slist);
+
+  return slist;
+}
+
+/* if simulate==TRUE, return whether accel_path can be changed to
+ * accel_key && accel_mods. otherwise, return whether accel_path
+ * was actually changed.
+ */
+static gboolean
+internal_change_entry (const gchar    *accel_path,
+                      guint           accel_key,
+                      GdkModifierType accel_mods,
+                      gboolean        replace,
+                      gboolean        simulate)
+{
+  GSList *node, *slist, *win_list, *group_list, *replace_list = NULL;
+  GHashTable *group_hm, *window_hm;
+  gboolean change_accel, removable, can_change = TRUE, seen_accel = FALSE;
+  GQuark entry_quark;
+  AccelEntry *entry = accel_path_lookup (accel_path);
+
+  /* not much todo if there's no entry yet */
+  if (!entry)
+    {
+      if (!simulate)
+       {
+         gtk_accel_map_add_entry (accel_path, 0, 0);
+         entry = accel_path_lookup (accel_path);
+          g_assert (entry);
+         entry->accel_key = accel_key;
+         entry->accel_mods = accel_mods;
+         entry->changed = TRUE;
+
+         do_accel_map_changed (entry);
+       }
+      return TRUE;
+    }
+
+  /* if there's nothing to change, not much todo either */
+  if (entry->accel_key == accel_key && entry->accel_mods == accel_mods)
+    {
+      if (!simulate)
+       entry->changed = TRUE;
+      return simulate ? TRUE : FALSE;
+    }
+
+  /* The no-change case has already been handled, so 
+   * simulate doesn't make a difference here.
+   */
+  if (entry->lock_count > 0)
+    return FALSE;
+
+  /* nobody's interested, easy going */
+  if (!entry->groups)
+    {
+      if (!simulate)
+       {
+         entry->accel_key = accel_key;
+         entry->accel_mods = accel_mods;
+         entry->changed = TRUE;
+
+         do_accel_map_changed (entry);
+       }
+      return TRUE;
+    }
+
+  /* 1) fetch all accel groups affected by this entry */
+  entry_quark = g_quark_try_string (entry->accel_path);
+  group_hm = g_hash_table_new (NULL, NULL);
+  window_hm = g_hash_table_new (NULL, NULL);
+  for (slist = entry->groups; slist; slist = slist->next)
+    g_hash_table_insert (group_hm, slist->data, slist->data);
+
+  /* 2) collect acceleratables affected */
+  group_list = g_hash_table_slist_values (group_hm);
+  for (slist = group_list; slist; slist = slist->next)
+    {
+      GtkAccelGroup *group = slist->data;
+
+      for (node = _gtk_accel_group_get_accelerables (group); node; node = node->next)
+       g_hash_table_insert (window_hm, node->data, node->data);
+    }
+  g_slist_free (group_list);
+
+  /* 3) include all accel groups used by acceleratables */
+  win_list = g_hash_table_slist_values (window_hm);
+  g_hash_table_destroy (window_hm);
+  for (slist = win_list; slist; slist = slist->next)
+    for (node = gtk_accel_groups_from_object (slist->data); node; node = node->next)
+      g_hash_table_insert (group_hm, node->data, node->data);
+  group_list = g_hash_table_slist_values (group_hm);
+  g_hash_table_destroy (group_hm);
+  
+  /* 4) walk the acceleratables and figure whether they occupy accel_key&accel_mods */
+  if (accel_key)
+    for (slist = win_list; slist; slist = slist->next)
+      if (GTK_IS_WINDOW (slist->data)) /* bad kludge in lack of a GtkAcceleratable */
+       if (_gtk_window_query_nonaccels (slist->data, accel_key, accel_mods))
+         {
+           seen_accel = TRUE;
+           break;
+         }
+  removable = !seen_accel;
+  
+  /* 5) walk all accel groups and search for locks */
+  if (removable)
+    for (slist = group_list; slist; slist = slist->next)
+      {
+       GtkAccelGroup *group = slist->data;
+       GtkAccelGroupEntry *ag_entry;
+       guint i, n;
+       
+       n = 0;
+       ag_entry = entry->accel_key ? gtk_accel_group_query (group, entry->accel_key, entry->accel_mods, &n) : NULL;
+       for (i = 0; i < n; i++)
+         if (ag_entry[i].accel_path_quark == entry_quark)
+           {
+             can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+             if (!can_change)
+               goto break_loop_step5;
+           }
+       
+       n = 0;
+       ag_entry = accel_key ? gtk_accel_group_query (group, accel_key, accel_mods, &n) : NULL;
+       for (i = 0; i < n; i++)
+         {
+           seen_accel = TRUE;
+           removable = !gtk_accel_group_get_is_locked (group) && !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+           if (!removable)
+             goto break_loop_step5;
+           if (ag_entry[i].accel_path_quark)
+             replace_list = g_slist_prepend (replace_list, GUINT_TO_POINTER (ag_entry[i].accel_path_quark));
+         }
+      }
+ break_loop_step5:
+  
+  /* 6) check whether we can remove existing accelerators */
+  if (removable && can_change)
+    for (slist = replace_list; slist; slist = slist->next)
+      if (!internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, TRUE))
+       {
+         removable = FALSE;
+         break;
+       }
+  
+  /* 7) check conditions and proceed if possible */
+  change_accel = can_change && (!seen_accel || (removable && replace));
+  
+  if (change_accel && !simulate)
+    {
+      /* ref accel groups */
+      for (slist = group_list; slist; slist = slist->next)
+       g_object_ref (slist->data);
+
+      /* 8) remove existing accelerators */
+      for (slist = replace_list; slist; slist = slist->next)
+       internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, FALSE);
+
+      /* 9) install new accelerator */
+      entry->accel_key = accel_key;
+      entry->accel_mods = accel_mods;
+      entry->changed = TRUE;
+
+      for (slist = group_list; slist; slist = slist->next)
+       _gtk_accel_group_reconnect (slist->data, g_quark_from_string (entry->accel_path));
+
+      /* unref accel groups */
+      for (slist = group_list; slist; slist = slist->next)
+       g_object_unref (slist->data);
+
+      do_accel_map_changed (entry);
+    }
+  g_slist_free (replace_list);
+  g_slist_free (group_list);
+  g_slist_free (win_list);
+
+  return change_accel;
+}
+
+/**
+ * gtk_accel_map_change_entry:
+ * @accel_path:  a valid accelerator path
+ * @accel_key:   the new accelerator key
+ * @accel_mods:  the new accelerator modifiers
+ * @replace:     %TRUE if other accelerators may be deleted upon conflicts
+ *
+ * Changes the @accel_key and @accel_mods currently associated with @accel_path.
+ * Due to conflicts with other accelerators, a change may not always be possible,
+ * @replace indicates whether other accelerators may be deleted to resolve such
+ * conflicts. A change will only occur if all conflicts could be resolved (which
+ * might not be the case if conflicting accelerators are locked). Successful
+ * changes are indicated by a %TRUE return value.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with
+ * g_intern_static_string().
+ *
+ * Returns: %TRUE if the accelerator could be changed, %FALSE otherwise
+ */
+gboolean
+gtk_accel_map_change_entry (const gchar    *accel_path,
+                           guint           accel_key,
+                           GdkModifierType accel_mods,
+                           gboolean        replace)
+{
+  g_return_val_if_fail (_gtk_accel_path_is_valid (accel_path), FALSE);
+
+  return internal_change_entry (accel_path, accel_key, accel_key ? accel_mods : 0, replace, FALSE);
+}
+
+static guint
+accel_map_parse_accel_path (GScanner *scanner)
+{
+  guint accel_key = 0;
+  GdkModifierType accel_mods = 0;
+  gchar *path, *accel;
+  
+  /* parse accel path */
+  g_scanner_get_next_token (scanner);
+  if (scanner->token != G_TOKEN_STRING)
+    return G_TOKEN_STRING;
+
+  /* test if the next token is an accelerator */
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != G_TOKEN_STRING)
+    {
+      /* if not so, eat that token and error out */
+      g_scanner_get_next_token (scanner);
+      return G_TOKEN_STRING;
+    }
+
+  /* get the full accelerator specification */
+  path = g_strdup (scanner->value.v_string);
+  g_scanner_get_next_token (scanner);
+  accel = g_strdup (scanner->value.v_string);
+
+  /* ensure the entry is present */
+  gtk_accel_map_add_entry (path, 0, 0);
+
+  /* and propagate it */
+  gtk_accelerator_parse (accel, &accel_key, &accel_mods);
+  gtk_accel_map_change_entry (path, accel_key, accel_mods, TRUE);
+
+  g_free (accel);
+  g_free (path);
+
+  /* check correct statement end */
+  g_scanner_get_next_token (scanner);
+  if (scanner->token != ')')
+    return ')';
+  else
+    return G_TOKEN_NONE;
+}
+
+static void
+accel_map_parse_statement (GScanner *scanner)
+{
+  guint expected_token;
+
+  g_scanner_get_next_token (scanner);
+
+  if (scanner->token == G_TOKEN_SYMBOL)
+    {
+      guint (*parser_func) (GScanner*);
+
+      parser_func = (guint (*) (GScanner *))scanner->value.v_symbol;
+
+      expected_token = parser_func (scanner);
+    }
+  else
+    expected_token = G_TOKEN_SYMBOL;
+
+  /* skip rest of statement on errrors
+   */
+  if (expected_token != G_TOKEN_NONE)
+    {
+      register guint level;
+
+      level = 1;
+      if (scanner->token == ')')
+       level--;
+      if (scanner->token == '(')
+       level++;
+
+      while (!g_scanner_eof (scanner) && level > 0)
+       {
+         g_scanner_get_next_token (scanner);
+
+         if (scanner->token == '(')
+           level++;
+         else if (scanner->token == ')')
+           level--;
+       }
+    }
+}
+
+/**
+ * gtk_accel_map_load_scanner:
+ * @scanner: a #GScanner which has already been provided with an input file
+ *
+ * #GScanner variant of gtk_accel_map_load().
+ */
+void
+gtk_accel_map_load_scanner (GScanner *scanner)
+{
+  gboolean skip_comment_single;
+  gboolean symbol_2_token;
+  gchar *cpair_comment_single;
+  gpointer saved_symbol;
+  
+  g_return_if_fail (scanner != NULL);
+
+  /* configure scanner */
+  skip_comment_single = scanner->config->skip_comment_single;
+  scanner->config->skip_comment_single = TRUE;
+  cpair_comment_single = scanner->config->cpair_comment_single;
+  scanner->config->cpair_comment_single = (char *) ";\n";
+  symbol_2_token = scanner->config->symbol_2_token;
+  scanner->config->symbol_2_token = FALSE;
+  saved_symbol = g_scanner_lookup_symbol (scanner, "gtk_accel_path");
+  g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", 
+                             accel_map_parse_accel_path);
+
+  /* outer parsing loop
+   */
+  g_scanner_peek_next_token (scanner);
+  while (scanner->next_token == '(')
+    {
+      g_scanner_get_next_token (scanner);
+
+      accel_map_parse_statement (scanner);
+
+      g_scanner_peek_next_token (scanner);
+    }
+
+  /* restore config */
+  scanner->config->skip_comment_single = skip_comment_single;
+  scanner->config->cpair_comment_single = cpair_comment_single;
+  scanner->config->symbol_2_token = symbol_2_token;
+  g_scanner_scope_remove_symbol (scanner, 0, "gtk_accel_path");
+  if (saved_symbol)
+    g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", saved_symbol);
+}
+
+/**
+ * gtk_accel_map_load_fd:
+ * @fd: a valid readable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_load().
+ *
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_load_fd (gint fd)
+{
+  GScanner *scanner;
+
+  g_return_if_fail (fd >= 0);
+
+  /* create and setup scanner */
+  scanner = g_scanner_new (NULL);
+  g_scanner_input_file (scanner, fd);
+
+  gtk_accel_map_load_scanner (scanner);
+
+  g_scanner_destroy (scanner);
+}
+
+/**
+ * gtk_accel_map_load:
+ * @file_name: (type filename): a file containing accelerator specifications,
+ *   in the GLib file name encoding
+ *
+ * Parses a file previously saved with gtk_accel_map_save() for
+ * accelerator specifications, and propagates them accordingly.
+ */
+void
+gtk_accel_map_load (const gchar *file_name)
+{
+  gint fd;
+
+  g_return_if_fail (file_name != NULL);
+
+  fd = g_open (file_name, O_RDONLY, 0);
+  if (fd < 0)
+    return;
+
+  gtk_accel_map_load_fd (fd);
+
+  close (fd);
+}
+
+static gboolean
+write_all (gint   fd,
+          gchar *buf,
+          gsize  to_write)
+{
+  while (to_write > 0)
+    {
+      gssize count = write (fd, buf, to_write);
+      if (count < 0)
+       {
+         if (errno != EINTR)
+           return FALSE;
+       }
+      else
+       {
+         to_write -= count;
+         buf += count;
+       }
+    }
+
+  return TRUE;
+}
+
+static void
+accel_map_print (gpointer        data,
+                const gchar    *accel_path,
+                guint           accel_key,
+                GdkModifierType accel_mods,
+                gboolean        changed)
+{
+  GString *gstring = g_string_new (changed ? NULL : "; ");
+  gint fd = GPOINTER_TO_INT (data);
+  gchar *tmp, *name;
+
+  g_string_append (gstring, "(gtk_accel_path \"");
+
+  tmp = g_strescape (accel_path, NULL);
+  g_string_append (gstring, tmp);
+  g_free (tmp);
+
+  g_string_append (gstring, "\" \"");
+
+  name = gtk_accelerator_name (accel_key, accel_mods);
+  tmp = g_strescape (name, NULL);
+  g_free (name);
+  g_string_append (gstring, tmp);
+  g_free (tmp);
+
+  g_string_append (gstring, "\")\n");
+
+  write_all (fd, gstring->str, gstring->len);
+
+  g_string_free (gstring, TRUE);
+}
+
+/**
+ * gtk_accel_map_save_fd:
+ * @fd: a valid writable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_save().
+ *
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_save_fd (gint fd)
+{
+  GString *gstring;
+
+  g_return_if_fail (fd >= 0);
+
+  gstring = g_string_new ("; ");
+  if (g_get_prgname ())
+    g_string_append (gstring, g_get_prgname ());
+  g_string_append (gstring, " GtkAccelMap rc-file         -*- scheme -*-\n");
+  g_string_append (gstring, "; this file is an automated accelerator map dump\n");
+  g_string_append (gstring, ";\n");
+
+  write_all (fd, gstring->str, gstring->len);
+  
+  g_string_free (gstring, TRUE);
+
+  gtk_accel_map_foreach (GINT_TO_POINTER (fd), accel_map_print);
+}
+
+/**
+ * gtk_accel_map_save:
+ * @file_name: (type filename): the name of the file to contain
+ *   accelerator specifications, in the GLib file name encoding
+ *
+ * Saves current accelerator specifications (accelerator path, key
+ * and modifiers) to @file_name.
+ * The file is written in a format suitable to be read back in by
+ * gtk_accel_map_load().
+ */
+void
+gtk_accel_map_save (const gchar *file_name)
+{
+  gint fd;
+
+  g_return_if_fail (file_name != NULL);
+
+  fd = g_open (file_name, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+  if (fd < 0)
+    return;
+
+  gtk_accel_map_save_fd (fd);
+
+  close (fd);
+}
+
+/**
+ * gtk_accel_map_foreach:
+ * @data: (allow-none): data to be passed into @foreach_func
+ * @foreach_func: (scope call): function to be executed for each accel
+ *                map entry which is not filtered out
+ *
+ * Loops over the entries in the accelerator map whose accel path 
+ * doesn’t match any of the filters added with gtk_accel_map_add_filter(), 
+ * and execute @foreach_func on each. The signature of @foreach_func is 
+ * that of #GtkAccelMapForeach, the @changed parameter indicates whether
+ * this accelerator was changed during runtime (thus, would need
+ * saving during an accelerator map dump).
+ */
+void
+gtk_accel_map_foreach (gpointer           data,
+                      GtkAccelMapForeach foreach_func)
+{
+  GSList *entries, *slist, *node;
+
+  g_return_if_fail (foreach_func != NULL);
+
+  entries = g_hash_table_slist_values (accel_entry_ht);
+  entries = g_slist_sort (entries, accel_entry_compare);
+
+  for (slist = entries; slist; slist = slist->next)
+    {
+      AccelEntry *entry = slist->data;
+      gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+      gboolean skip = FALSE;
+
+      for (node = accel_filters; node; node = node->next)
+        if (g_pattern_match_string (node->data, entry->accel_path))
+          {
+            skip = TRUE;
+            break;
+          }
+
+      if (!skip)
+        foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+    }
+  g_slist_free (entries);
+}
+
+/**
+ * gtk_accel_map_foreach_unfiltered:
+ * @data:         data to be passed into @foreach_func
+ * @foreach_func: (scope call): function to be executed for each accel
+ *                map entry
+ *
+ * Loops over all entries in the accelerator map, and execute
+ * @foreach_func on each. The signature of @foreach_func is that of
+ * #GtkAccelMapForeach, the @changed parameter indicates whether
+ * this accelerator was changed during runtime (thus, would need
+ * saving during an accelerator map dump).
+ */
+void
+gtk_accel_map_foreach_unfiltered (gpointer           data,
+                                 GtkAccelMapForeach foreach_func)
+{
+  GSList *entries, *slist;
+
+  g_return_if_fail (foreach_func != NULL);
+
+  entries = g_hash_table_slist_values (accel_entry_ht);
+  for (slist = entries; slist; slist = slist->next)
+    {
+      AccelEntry *entry = slist->data;
+      gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+
+      foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+    }
+  g_slist_free (entries);
+}
+
+/**
+ * gtk_accel_map_add_filter:
+ * @filter_pattern: a pattern (see #GPatternSpec)
+ *
+ * Adds a filter to the global list of accel path filters.
+ *
+ * Accel map entries whose accel path matches one of the filters
+ * are skipped by gtk_accel_map_foreach().
+ *
+ * This function is intended for GTK+ modules that create their own
+ * menus, but don’t want them to be saved into the applications accelerator
+ * map dump.
+ */
+void
+gtk_accel_map_add_filter (const gchar *filter_pattern)
+{
+  GPatternSpec *pspec;
+  GSList *slist;
+
+  g_return_if_fail (filter_pattern != NULL);
+
+  pspec = g_pattern_spec_new (filter_pattern);
+  for (slist = accel_filters; slist; slist = slist->next)
+    if (g_pattern_spec_equal (pspec, slist->data))
+      {
+       g_pattern_spec_free (pspec);
+       return;
+      }
+  accel_filters = g_slist_prepend (accel_filters, pspec);
+}
+
+void
+_gtk_accel_map_add_group (const gchar   *accel_path,
+                         GtkAccelGroup *accel_group)
+{
+  AccelEntry *entry;
+
+  g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  entry = accel_path_lookup (accel_path);
+  if (!entry)
+    {
+      gtk_accel_map_add_entry (accel_path, 0, 0);
+      entry = accel_path_lookup (accel_path);
+    }
+  entry->groups = g_slist_prepend (entry->groups, accel_group);
+}
+
+void
+_gtk_accel_map_remove_group (const gchar   *accel_path,
+                            GtkAccelGroup *accel_group)
+{
+  AccelEntry *entry;
+
+  entry = accel_path_lookup (accel_path);
+  g_return_if_fail (entry != NULL);
+  g_return_if_fail (g_slist_find (entry->groups, accel_group));
+
+  entry->groups = g_slist_remove (entry->groups, accel_group);
+}
+
+
+/**
+ * gtk_accel_map_lock_path:
+ * @accel_path: a valid accelerator path
+ * 
+ * Locks the given accelerator path. If the accelerator map doesn’t yet contain
+ * an entry for @accel_path, a new one is created.
+ *
+ * Locking an accelerator path prevents its accelerator from being changed 
+ * during runtime. A locked accelerator path can be unlocked by 
+ * gtk_accel_map_unlock_path(). Refer to gtk_accel_map_change_entry() 
+ * for information about runtime accelerator changes.
+ *
+ * If called more than once, @accel_path remains locked until
+ * gtk_accel_map_unlock_path() has been called an equivalent number
+ * of times.
+ *
+ * Note that locking of individual accelerator paths is independent from 
+ * locking the #GtkAccelGroup containing them. For runtime accelerator
+ * changes to be possible, both the accelerator path and its #GtkAccelGroup
+ * have to be unlocked. 
+ **/
+void 
+gtk_accel_map_lock_path (const gchar *accel_path)
+{
+  AccelEntry *entry;
+
+  g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+  entry = accel_path_lookup (accel_path);
+  
+  if (!entry)
+    {
+      gtk_accel_map_add_entry (accel_path, 0, 0);
+      entry = accel_path_lookup (accel_path);
+    }
+
+  entry->lock_count += 1;
+}
+
+/**
+ * gtk_accel_map_unlock_path:
+ * @accel_path: a valid accelerator path
+ * 
+ * Undoes the last call to gtk_accel_map_lock_path() on this @accel_path.
+ * Refer to gtk_accel_map_lock_path() for information about accelerator path locking.
+ **/
+void 
+gtk_accel_map_unlock_path (const gchar *accel_path)
+{
+  AccelEntry *entry;
+
+  g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+  entry = accel_path_lookup (accel_path);
+
+  g_return_if_fail (entry != NULL && entry->lock_count > 0);
+
+  entry->lock_count -= 1;  
+}
+
+G_DEFINE_TYPE (GtkAccelMap, gtk_accel_map, G_TYPE_OBJECT)
+
+static void
+gtk_accel_map_class_init (GtkAccelMapClass *accel_map_class)
+{
+  /**
+   * GtkAccelMap::changed:
+   * @object: the global accel map object
+   * @accel_path: the path of the accelerator that changed
+   * @accel_key: the key value for the new accelerator
+   * @accel_mods: the modifier mask for the new accelerator
+   *
+   * Notifies of a change in the global accelerator map.
+   * The path is also used as the detail for the signal,
+   * so it is possible to connect to
+   * changed::`accel_path`.
+   */
+  accel_map_signals[CHANGED] = g_signal_new (I_("changed"),
+                                            G_TYPE_FROM_CLASS (accel_map_class),
+                                            G_SIGNAL_DETAILED|G_SIGNAL_RUN_LAST,
+                                            0,
+                                            NULL, NULL,
+                                            _gtk_marshal_VOID__STRING_UINT_FLAGS,
+                                            G_TYPE_NONE, 3,
+                                            G_TYPE_STRING, G_TYPE_UINT, GDK_TYPE_MODIFIER_TYPE);
+}
+
+static void
+gtk_accel_map_init (GtkAccelMap *map)
+{
+}
+
+static GtkAccelMap *accel_map;
+
+/**
+ * gtk_accel_map_get:
+ * 
+ * Gets the singleton global #GtkAccelMap object. This object
+ * is useful only for notification of changes to the accelerator
+ * map via the ::changed signal; it isn’t a parameter to the
+ * other accelerator map functions.
+ * 
+ * Returns: (transfer none): the global #GtkAccelMap object
+ **/
+GtkAccelMap *
+gtk_accel_map_get (void)
+{
+  if (!accel_map)
+    accel_map = g_object_new (GTK_TYPE_ACCEL_MAP, NULL);
+
+  return accel_map;
+}
+
+static void
+do_accel_map_changed (AccelEntry *entry)
+{
+  if (accel_map)
+    g_signal_emit (accel_map,
+                  accel_map_signals[CHANGED],
+                  g_quark_from_string (entry->accel_path),
+                  entry->accel_path,
+                  entry->accel_key,
+                  entry->accel_mods);
+}
+
+gchar *
+_gtk_accel_path_for_action (const gchar *action_name,
+                            GVariant    *parameter)
+{
+  GString *s;
+
+  s = g_string_new ("<GAction>/");
+  g_string_append (s, action_name);
+  if (parameter)
+    {
+      g_string_append_c (s, '/');
+      g_variant_print_string (parameter, s, FALSE);
+    }
+  return g_string_free (s, FALSE);
+}
+
diff --git a/gtk/gtkaccelmap.h b/gtk/gtkaccelmap.h
new file mode 100644 (file)
index 0000000..e04f251
--- /dev/null
@@ -0,0 +1,109 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_ACCEL_MAP_H__
+#define __GTK_ACCEL_MAP_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkaccelgroup.h>
+
+G_BEGIN_DECLS
+
+/* --- global GtkAccelMap object --- */
+#define GTK_TYPE_ACCEL_MAP                (gtk_accel_map_get_type ())
+#define GTK_ACCEL_MAP(accel_map)         (G_TYPE_CHECK_INSTANCE_CAST ((accel_map), GTK_TYPE_ACCEL_MAP, GtkAccelMap))
+#define GTK_ACCEL_MAP_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_MAP, GtkAccelMapClass))
+#define GTK_IS_ACCEL_MAP(accel_map)      (G_TYPE_CHECK_INSTANCE_TYPE ((accel_map), GTK_TYPE_ACCEL_MAP))
+#define GTK_IS_ACCEL_MAP_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ACCEL_MAP))
+#define GTK_ACCEL_MAP_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACCEL_MAP, GtkAccelMapClass))
+
+typedef struct _GtkAccelMap      GtkAccelMap;
+typedef struct _GtkAccelMapClass GtkAccelMapClass;
+
+/* --- notifier --- */
+/**
+ * GtkAccelMapForeach:
+ * @data: User data passed to gtk_accel_map_foreach() or
+ *  gtk_accel_map_foreach_unfiltered()
+ * @accel_path: Accel path of the current accelerator
+ * @accel_key: Key of the current accelerator
+ * @accel_mods: Modifiers of the current accelerator
+ * @changed: Changed flag of the accelerator (if %TRUE, accelerator has changed
+ *  during runtime and would need to be saved during an accelerator dump)
+ */
+typedef void (*GtkAccelMapForeach)             (gpointer        data,
+                                                const gchar    *accel_path,
+                                                guint           accel_key,
+                                                GdkModifierType accel_mods,
+                                                gboolean        changed);
+
+
+/* --- public API --- */
+
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_add_entry      (const gchar            *accel_path,
+                                        guint                   accel_key,
+                                        GdkModifierType         accel_mods);
+GDK_AVAILABLE_IN_ALL
+gboolean   gtk_accel_map_lookup_entry  (const gchar            *accel_path,
+                                        GtkAccelKey            *key);
+GDK_AVAILABLE_IN_ALL
+gboolean   gtk_accel_map_change_entry  (const gchar            *accel_path,
+                                        guint                   accel_key,
+                                        GdkModifierType         accel_mods,
+                                        gboolean                replace);
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_load           (const gchar            *file_name);
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_save           (const gchar            *file_name);
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_foreach        (gpointer                data,
+                                        GtkAccelMapForeach      foreach_func);
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_load_fd        (gint                    fd);
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_load_scanner   (GScanner               *scanner);
+GDK_AVAILABLE_IN_ALL
+void      gtk_accel_map_save_fd        (gint                    fd);
+
+GDK_AVAILABLE_IN_ALL
+void       gtk_accel_map_lock_path      (const gchar            *accel_path);
+GDK_AVAILABLE_IN_ALL
+void       gtk_accel_map_unlock_path    (const gchar            *accel_path);
+
+/* --- filter functions --- */
+GDK_AVAILABLE_IN_ALL
+void   gtk_accel_map_add_filter         (const gchar           *filter_pattern);
+GDK_AVAILABLE_IN_ALL
+void   gtk_accel_map_foreach_unfiltered (gpointer               data,
+                                         GtkAccelMapForeach     foreach_func);
+
+/* --- notification --- */
+GDK_AVAILABLE_IN_ALL
+GType        gtk_accel_map_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkAccelMap *gtk_accel_map_get      (void);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkAccelMap, g_object_unref)
+
+G_END_DECLS
+
+#endif /* __GTK_ACCEL_MAP_H__ */
diff --git a/gtk/gtkaccelmapprivate.h b/gtk/gtkaccelmapprivate.h
new file mode 100644 (file)
index 0000000..8be1e5e
--- /dev/null
@@ -0,0 +1,39 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_ACCEL_MAP_PRIVATE_H__
+#define __GTK_ACCEL_MAP_PRIVATE_H__
+
+
+#include <gtk/gtkaccelmap.h>
+
+G_BEGIN_DECLS
+
+void            _gtk_accel_map_init         (void);
+
+void            _gtk_accel_map_add_group    (const gchar   *accel_path,
+                                             GtkAccelGroup *accel_group);
+void            _gtk_accel_map_remove_group (const gchar   *accel_path,
+                                             GtkAccelGroup *accel_group);
+gboolean        _gtk_accel_path_is_valid    (const gchar   *accel_path);
+
+gchar         * _gtk_accel_path_for_action  (const gchar   *action_name,
+                                             GVariant      *parameter);
+
+G_END_DECLS
+
+#endif /* __GTK_ACCEL_MAP_PRIVATE_H__ */
index efd2e3a55fd8d8dd8c8262a88c770413f7e65f96..768915c807f9508ccda486c7ed9deb24175669aa 100644 (file)
@@ -37,6 +37,7 @@
 #include "gtkmarshalers.h"
 #include "gtkmain.h"
 #include "gtkrecentmanager.h"
+#include "gtkaccelmapprivate.h"
 #include "gtkicontheme.h"
 #include "gtkbuilder.h"
 #include "gtkshortcutswindow.h"
index e4e60bfc4b02e899c4e4fdc9f0bc32cfb8c13aad..a27501facffbf11179731ed04d6b05ff478a5a22 100644 (file)
 #include "config.h"
 
 #include "gtkapplicationaccelsprivate.h"
-
 #include "gtkactionmuxerprivate.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcuttrigger.h"
+
+#include <string.h>
+
+typedef struct
+{
+  guint           key;
+  GdkModifierType modifier;
+} AccelKey;
 
 struct _GtkApplicationAccels
 {
   GObject parent;
 
-  GListModel *shortcuts;
+  GHashTable *action_to_accels;
+  GHashTable *accel_to_actions;
 };
 
 G_DEFINE_TYPE (GtkApplicationAccels, gtk_application_accels, G_TYPE_OBJECT)
 
+static AccelKey *
+accel_key_copy (const AccelKey *source)
+{
+  AccelKey *dest;
+
+  dest = g_slice_new (AccelKey);
+  dest->key = source->key;
+  dest->modifier = source->modifier;
+
+  return dest;
+}
+
+static void
+accel_key_free (gpointer data)
+{
+  AccelKey *key = data;
+
+  g_slice_free (AccelKey, key);
+}
+
+static guint
+accel_key_hash (gconstpointer data)
+{
+  const AccelKey *key = data;
+
+  return key->key + (key->modifier << 16);
+}
+
+static gboolean
+accel_key_equal (gconstpointer a,
+                 gconstpointer b)
+{
+  const AccelKey *ak = a;
+  const AccelKey *bk = b;
+
+  return ak->key == bk->key && ak->modifier == bk->modifier;
+}
+
+static void
+add_entry (GtkApplicationAccels *accels,
+           AccelKey             *key,
+           const gchar          *action_and_target)
+{
+  const gchar **old;
+  const gchar **new;
+  gint n;
+
+  old = g_hash_table_lookup (accels->accel_to_actions, key);
+  if (old != NULL)
+    for (n = 0; old[n]; n++)  /* find the length */
+      ;
+  else
+    n = 0;
+
+  new = g_renew (const gchar *, old, n + 1 + 1);
+  new[n] = action_and_target;
+  new[n + 1] = NULL;
+
+  g_hash_table_insert (accels->accel_to_actions, accel_key_copy (key), new);
+}
+
+static void
+remove_entry (GtkApplicationAccels *accels,
+              AccelKey             *key,
+              const gchar          *action_and_target)
+{
+  const gchar **old;
+  const gchar **new;
+  gint n, i;
+
+  /* if we can't find the entry then something has gone very wrong... */
+  old = g_hash_table_lookup (accels->accel_to_actions, key);
+  g_assert (old != NULL);
+
+  for (n = 0; old[n]; n++)  /* find the length */
+    ;
+  g_assert_cmpint (n, >, 0);
+
+  if (n == 1)
+    {
+      /* The simple case of removing the last action for an accel. */
+      g_assert_cmpstr (old[0], ==, action_and_target);
+      g_hash_table_remove (accels->accel_to_actions, key);
+      return;
+    }
+
+  for (i = 0; i < n; i++)
+    if (g_str_equal (old[i], action_and_target))
+      break;
+
+  /* We must have found it... */
+  g_assert_cmpint (i, <, n);
+
+  new = g_new (const gchar *, n - 1 + 1);
+  memcpy (new, old, i * sizeof (const gchar *));
+  memcpy (new + i, old + i + 1, (n - (i + 1)) * sizeof (const gchar *));
+  new[n - 1] = NULL;
+
+  g_hash_table_insert (accels->accel_to_actions, accel_key_copy (key), new);
+}
+
 static void
 gtk_application_accels_finalize (GObject *object)
 {
   GtkApplicationAccels *accels = GTK_APPLICATION_ACCELS (object);
 
-  g_list_store_remove_all (G_LIST_STORE (accels->shortcuts));
-  g_object_unref (accels->shortcuts);
+  g_hash_table_unref (accels->accel_to_actions);
+  g_hash_table_unref (accels->action_to_accels);
 
   G_OBJECT_CLASS (gtk_application_accels_parent_class)->finalize (object);
 }
@@ -59,7 +165,9 @@ gtk_application_accels_class_init (GtkApplicationAccelsClass *klass)
 static void
 gtk_application_accels_init (GtkApplicationAccels *accels)
 {
-  accels->shortcuts = G_LIST_MODEL (g_list_store_new (GTK_TYPE_SHORTCUT));
+  accels->accel_to_actions = g_hash_table_new_full (accel_key_hash, accel_key_equal,
+                                                    accel_key_free, g_free);
+  accels->action_to_accels = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 }
 
 GtkApplicationAccels *
@@ -73,97 +181,54 @@ gtk_application_accels_set_accels_for_action (GtkApplicationAccels *accels,
                                               const gchar          *detailed_action_name,
                                               const gchar * const  *accelerators)
 {
-  gchar *action_name;
-  GVariant *target;
-  GtkShortcut *shortcut;
-  GtkShortcutTrigger *trigger = NULL;
-  GError *error = NULL;
-  guint i;
-
-  if (!g_action_parse_detailed_name (detailed_action_name, &action_name, &target, &error))
-    {
-      g_critical ("Error parsing action name: %s", error->message);
-      g_error_free (error);
-      return;
-    }
-
-  /* remove the accelerator if it already exists */
-  for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
-    {
-      GtkShortcut *shortcut_i = g_list_model_get_item (accels->shortcuts, i);
-      GtkShortcutAction *action = gtk_shortcut_get_action (shortcut_i);
-      GVariant *args = gtk_shortcut_get_arguments (shortcut_i);
-
-      if (gtk_shortcut_action_get_action_type (action) != GTK_SHORTCUT_ACTION_ACTION ||
-          !g_str_equal (gtk_action_action_get_name (action), action_name))
-        continue;
+  gchar *action_and_target;
+  AccelKey *keys, *old_keys;
+  gint i, n;
 
-      if ((target == NULL && args != NULL) ||
-          (target != NULL && (args == NULL || !g_variant_equal (target, args))))
-        continue;
-
-      g_list_store_remove (G_LIST_STORE (accels->shortcuts), i);
-      break;
-    }
+  action_and_target = gtk_normalise_detailed_action_name (detailed_action_name);
 
-  if (accelerators == NULL)
-    goto out;
+  n = accelerators ? g_strv_length ((gchar **) accelerators) : 0;
 
-  for (i = 0; accelerators[i]; i++)
+  if (n > 0)
     {
-      GtkShortcutTrigger *new_trigger;
-      guint key, modifier;
+      keys = g_new0 (AccelKey, n + 1);
 
-      if (!gtk_accelerator_parse (accelerators[i], &key, &modifier))
+      for (i = 0; i < n; i++)
         {
-          g_critical ("Unable to parse accelerator '%s': ignored request to install accelerators",
-                      accelerators[i]);
-          if (trigger)
-            gtk_shortcut_trigger_unref (trigger);
-          goto out;;
+          gtk_accelerator_parse (accelerators[i], &keys[i].key, &keys[i].modifier);
+
+          if (keys[i].key == 0)
+            {
+              g_warning ("Unable to parse accelerator '%s': ignored request to install %d accelerators",
+                         accelerators[i], n);
+              g_free (action_and_target);
+              g_free (keys);
+              return;
+            }
         }
-      new_trigger = gtk_keyval_trigger_new (key, modifier);
-      if (trigger)
-        trigger = gtk_alternative_trigger_new (trigger, new_trigger);
-      else
-        trigger = new_trigger;
     }
-  if (trigger == NULL)
-    goto out;
-
-  shortcut = gtk_shortcut_new (trigger, gtk_action_action_new (action_name));
-  gtk_shortcut_set_arguments (shortcut, target);
-  g_list_store_append (G_LIST_STORE (accels->shortcuts), shortcut);
-  g_object_unref (shortcut);
-
-out:
-  g_free (action_name);
-  if (target)
-    g_variant_unref (target);
-}
+  else
+    keys = NULL;
 
-static void
-append_accelerators (GPtrArray          *accels,
-                     GtkShortcutTrigger *trigger)
-{
-  switch (gtk_shortcut_trigger_get_trigger_type (trigger))
+  old_keys = g_hash_table_lookup (accels->action_to_accels, action_and_target);
+  if (old_keys)
     {
-    case GTK_SHORTCUT_TRIGGER_KEYVAL:
-      g_ptr_array_add (accels,
-                       gtk_accelerator_name (gtk_keyval_trigger_get_keyval (trigger),
-                                             gtk_keyval_trigger_get_modifiers (trigger)));
-      return;
+      /* We need to remove accel entries from existing keys */
+      for (i = 0; old_keys[i].key; i++)
+        remove_entry (accels, &old_keys[i], action_and_target);
+    }
 
-    case GTK_SHORTCUT_TRIGGER_ALTERNATIVE:
-      append_accelerators (accels, gtk_alternative_trigger_get_first (trigger));
-      append_accelerators (accels, gtk_alternative_trigger_get_second (trigger));
-      return;
+  if (keys)
+    {
+      g_hash_table_replace (accels->action_to_accels, action_and_target, keys);
 
-    case GTK_SHORTCUT_TRIGGER_MNEMONIC:
-    case GTK_SHORTCUT_TRIGGER_NEVER:
-    default:
-      /* not an accelerator */
-      return;
+      for (i = 0; i < n; i++)
+        add_entry (accels, &keys[i], action_and_target);
+    }
+  else
+    {
+      g_hash_table_remove (accels->action_to_accels, action_and_target);
+      g_free (action_and_target);
     }
 }
 
@@ -171,137 +236,223 @@ gchar **
 gtk_application_accels_get_accels_for_action (GtkApplicationAccels *accels,
                                               const gchar          *detailed_action_name)
 {
-  GPtrArray *result;
-  char *action_name;
-  GVariant *target;
-  GError *error = NULL;
-  guint i;
+  gchar *action_and_target;
+  AccelKey *keys;
+  gchar **result;
+  gint n, i = 0;
 
-  result = g_ptr_array_new ();
+  action_and_target = gtk_normalise_detailed_action_name (detailed_action_name);
 
-  if (!g_action_parse_detailed_name (detailed_action_name, &action_name, &target, &error))
+  keys = g_hash_table_lookup (accels->action_to_accels, action_and_target);
+  if (!keys)
     {
-      g_critical ("Error parsing action name: %s", error->message);
-      g_error_free (error);
-      g_ptr_array_add (result, NULL);
-      return (gchar **) g_ptr_array_free (result, FALSE);
+      g_free (action_and_target);
+      return g_new0 (gchar *, 0 + 1);
     }
 
-  for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
-    {
-      GtkShortcut *shortcut = g_list_model_get_item (accels->shortcuts, i);
-      GtkShortcutAction *action = gtk_shortcut_get_action (shortcut);
-      GVariant *args = gtk_shortcut_get_arguments (shortcut);
+  for (n = 0; keys[n].key; n++)
+    ;
 
-      if (gtk_shortcut_action_get_action_type (action) != GTK_SHORTCUT_ACTION_ACTION ||
-          !g_str_equal (gtk_action_action_get_name (action), action_name))
-        continue;
+  result = g_new0 (gchar *, n + 1);
 
-      if ((target == NULL && args != NULL) ||
-          (target != NULL && (args == NULL || !g_variant_equal (target, args))))
-        continue;
-
-      append_accelerators (result, gtk_shortcut_get_trigger (shortcut));
-      break;
-    }
+  for (i = 0; i < n; i++)
+    result[i] = gtk_accelerator_name (keys[i].key, keys[i].modifier);
 
-  g_free (action_name);
-  if (target)
-    g_variant_unref (target);
-  g_ptr_array_add (result, NULL);
-  return (gchar **) g_ptr_array_free (result, FALSE);
+  g_free (action_and_target);
+  return result;
 }
 
-static gboolean
-trigger_matches_accel (GtkShortcutTrigger *trigger,
-                       guint               keyval,
-                       GdkModifierType     modifiers)
+gchar **
+gtk_application_accels_get_actions_for_accel (GtkApplicationAccels *accels,
+                                              const gchar          *accel)
 {
-  switch (gtk_shortcut_trigger_get_trigger_type (trigger))
+  const gchar * const *actions_and_targets;
+  gchar **detailed_actions;
+  AccelKey accel_key;
+  guint i, n;
+
+  gtk_accelerator_parse (accel, &accel_key.key, &accel_key.modifier);
+
+  if (accel_key.key == 0)
     {
-    case GTK_SHORTCUT_TRIGGER_KEYVAL:
-      return gtk_keyval_trigger_get_keyval (trigger) == keyval
-          && gtk_keyval_trigger_get_modifiers (trigger) == modifiers;
-
-    case GTK_SHORTCUT_TRIGGER_ALTERNATIVE:
-      return trigger_matches_accel (gtk_alternative_trigger_get_first (trigger), keyval, modifiers)
-          || trigger_matches_accel (gtk_alternative_trigger_get_second (trigger), keyval, modifiers);
-
-    case GTK_SHORTCUT_TRIGGER_MNEMONIC:
-    case GTK_SHORTCUT_TRIGGER_NEVER:
-    default:
-      return FALSE;
+      g_critical ("invalid accelerator string '%s'", accel);
+      g_return_val_if_fail (accel_key.key != 0, NULL);
     }
-}
 
-static char *
-get_detailed_name_for_shortcut (GtkShortcut *shortcut)
-{
-  GtkShortcutAction *action = gtk_shortcut_get_action (shortcut);
+  actions_and_targets = g_hash_table_lookup (accels->accel_to_actions, &accel_key);
+  n = actions_and_targets ? g_strv_length ((gchar **) actions_and_targets) : 0;
 
-  if (gtk_shortcut_action_get_action_type (action) != GTK_SHORTCUT_ACTION_ACTION)
-    return NULL;
+  detailed_actions = g_new0 (gchar *, n + 1);
 
-  return g_action_print_detailed_name (gtk_action_action_get_name (action), gtk_shortcut_get_arguments (shortcut));
+  for (i = 0; i < n; i++)
+    {
+      const gchar *action_and_target = actions_and_targets[i];
+      const gchar *sep;
+      GVariant *target;
+
+      sep = strrchr (action_and_target, '|');
+      target = g_variant_parse (NULL, action_and_target, sep, NULL, NULL);
+      detailed_actions[i] = g_action_print_detailed_name (sep + 1, target);
+      if (target)
+        g_variant_unref (target);
+    }
+
+  detailed_actions[n] = NULL;
+
+  return detailed_actions;
 }
 
 gchar **
-gtk_application_accels_get_actions_for_accel (GtkApplicationAccels *accels,
-                                              const gchar          *accel)
+gtk_application_accels_list_action_descriptions (GtkApplicationAccels *accels)
 {
-  GPtrArray *result;
-  guint key, modifiers;
-  guint i;
+  GHashTableIter iter;
+  gchar **result;
+  gint n, i = 0;
+  gpointer key;
 
-  if (!gtk_accelerator_parse (accel, &key, &modifiers))
-    {
-      g_critical ("invalid accelerator string '%s'", accel);
-      return NULL;
-    }
+  n = g_hash_table_size (accels->action_to_accels);
+  result = g_new (gchar *, n + 1);
 
-  result = g_ptr_array_new ();
-  
-  for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
+  g_hash_table_iter_init (&iter, accels->action_to_accels);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
     {
-      GtkShortcut *shortcut = g_list_model_get_item (accels->shortcuts, i);
-      char *detailed_name;
-
-      if (!trigger_matches_accel (gtk_shortcut_get_trigger (shortcut), key, modifiers))
-        continue;
-      
-      detailed_name = get_detailed_name_for_shortcut (shortcut);
-      if (detailed_name)
-        g_ptr_array_add (result, detailed_name);
+      const gchar *action_and_target = key;
+      const gchar *sep;
+      GVariant *target;
+
+      sep = strrchr (action_and_target, '|');
+      target = g_variant_parse (NULL, action_and_target, sep, NULL, NULL);
+      result[i++] = g_action_print_detailed_name (sep + 1, target);
+      if (target)
+        g_variant_unref (target);
     }
+  g_assert_cmpint (i, ==, n);
+  result[i] = NULL;
 
-  g_ptr_array_add (result, NULL);
-  return (gchar **) g_ptr_array_free (result, FALSE);
+  return result;
 }
 
-gchar **
-gtk_application_accels_list_action_descriptions (GtkApplicationAccels *accels)
+void
+gtk_application_accels_foreach_key (GtkApplicationAccels     *accels,
+                                    GtkWindow                *window,
+                                    GtkWindowKeysForeachFunc  callback,
+                                    gpointer                  user_data)
 {
-  GPtrArray *result;
-  guint i;
+  GHashTableIter iter;
+  gpointer key;
 
-  result = g_ptr_array_new ();
-  
-  for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
+  g_hash_table_iter_init (&iter, accels->accel_to_actions);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
     {
-      GtkShortcut *shortcut = g_list_model_get_item (accels->shortcuts, i);
-      char *detailed_name;
+      AccelKey *accel_key = key;
 
-      detailed_name = get_detailed_name_for_shortcut (shortcut);
-      if (detailed_name)
-        g_ptr_array_add (result, detailed_name);
+      (* callback) (window, accel_key->key, accel_key->modifier, FALSE, user_data);
     }
-
-  g_ptr_array_add (result, NULL);
-  return (gchar **) g_ptr_array_free (result, FALSE);
 }
 
-GListModel *
-gtk_application_accels_get_shortcuts (GtkApplicationAccels *accels)
+gboolean
+gtk_application_accels_activate (GtkApplicationAccels *accels,
+                                 GActionGroup         *action_group,
+                                 guint                 key,
+                                 GdkModifierType       modifier)
 {
-  return accels->shortcuts;
+  AccelKey accel_key = { key, modifier };
+  const gchar **actions;
+  gint i;
+
+  actions = g_hash_table_lookup (accels->accel_to_actions, &accel_key);
+
+  if (actions == NULL)
+    return FALSE;
+
+  /* We may have more than one action on a given accel.  This could be
+   * the case if we have different types of windows with different
+   * actions in each.
+   *
+   * Find the first one that will successfully activate and use it.
+   */
+  for (i = 0; actions[i]; i++)
+    {
+      const GVariantType *parameter_type;
+      const gchar *action_name;
+      const gchar *sep;
+      gboolean enabled;
+      GVariant *target;
+
+      sep = strrchr (actions[i], '|');
+      action_name = sep + 1;
+
+      if (!g_action_group_query_action (action_group, action_name, &enabled, &parameter_type, NULL, NULL, NULL))
+        continue;
+
+      if (!enabled)
+        continue;
+
+      /* We found an action with the correct name and it's enabled.
+       * This is the action that we are going to try to invoke.
+       *
+       * There is still the possibility that the target value doesn't
+       * match the expected parameter type.  In that case, we will print
+       * a warning.
+       *
+       * Note: we want to hold a ref on the target while we're invoking
+       * the action to prevent trouble if someone uninstalls the accel
+       * from the handler.  That's not a problem since we're parsing it.
+       */
+      if (actions[i] != sep) /* if it has a target... */
+        {
+          GError *error = NULL;
+
+          if (parameter_type == NULL)
+            {
+              gchar *accel_str = gtk_accelerator_name (key, modifier);
+              g_warning ("Accelerator '%s' tries to invoke action '%s' with target, but action has no parameter",
+                         accel_str, action_name);
+              g_free (accel_str);
+              return TRUE;
+            }
+
+          target = g_variant_parse (NULL, actions[i], sep, NULL, &error);
+          g_assert_no_error (error);
+          g_assert (target);
+
+          if (!g_variant_is_of_type (target, parameter_type))
+            {
+              gchar *accel_str = gtk_accelerator_name (key, modifier);
+              gchar *typestr = g_variant_type_dup_string (parameter_type);
+              gchar *targetstr = g_variant_print (target, TRUE);
+              g_warning ("Accelerator '%s' tries to invoke action '%s' with target '%s',"
+                         " but action expects parameter with type '%s'", accel_str, action_name, targetstr, typestr);
+              g_variant_unref (target);
+              g_free (targetstr);
+              g_free (accel_str);
+              g_free (typestr);
+              return TRUE;
+            }
+        }
+      else
+        {
+          if (parameter_type != NULL)
+            {
+              gchar *accel_str = gtk_accelerator_name (key, modifier);
+              gchar *typestr = g_variant_type_dup_string (parameter_type);
+              g_warning ("Accelerator '%s' tries to invoke action '%s' without target,"
+                         " but action expects parameter with type '%s'", accel_str, action_name, typestr);
+              g_free (accel_str);
+              g_free (typestr);
+              return TRUE;
+            }
+
+          target = NULL;
+        }
+
+      g_action_group_activate_action (action_group, action_name, target);
+
+      if (target)
+        g_variant_unref (target);
+
+      return TRUE;
+    }
+
+  return FALSE;
 }
index fbde7da3688cab1a5cbac933d7772cac35161134..b126401a780f3a11ccbaa224ec51cef0f3b94f5b 100644 (file)
@@ -47,7 +47,15 @@ gchar **        gtk_application_accels_get_actions_for_accel        (GtkApplicat
 
 gchar **        gtk_application_accels_list_action_descriptions     (GtkApplicationAccels *accels);
 
-GListModel *    gtk_application_accels_get_shortcuts                (GtkApplicationAccels *accels);
+void            gtk_application_accels_foreach_key                  (GtkApplicationAccels     *accels,
+                                                                     GtkWindow                *window,
+                                                                     GtkWindowKeysForeachFunc  callback,
+                                                                     gpointer                  user_data);
+
+gboolean        gtk_application_accels_activate                     (GtkApplicationAccels *accels,
+                                                                     GActionGroup         *action_group,
+                                                                     guint                 key,
+                                                                     GdkModifierType       modifier);
 
 G_END_DECLS
 
index b0b46c1dd2048d6e99f07b7c4ab0f5fad2595aa9..4161e2d1b437f9b25b8bf958830fb93fd8662b8c 100644 (file)
@@ -65,6 +65,7 @@
 
 #include "gtkassistant.h"
 
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkbuildable.h"
 #include "gtkbutton.h"
@@ -509,6 +510,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
   GtkWindowClass *window_class;
+  GtkBindingSet *binding_set;
 
   gobject_class   = (GObjectClass *) class;
   widget_class    = (GtkWidgetClass *) class;
@@ -617,10 +619,8 @@ gtk_assistant_class_init (GtkAssistantClass *class)
                                 NULL,
                                 G_TYPE_NONE, 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Escape, 0,
-                                       "escape",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (class);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "escape", 0);
 
   /**
    * GtkAssistant:use-header-bar:
diff --git a/gtk/gtkbindings.c b/gtk/gtkbindings.c
new file mode 100644 (file)
index 0000000..9f3d879
--- /dev/null
@@ -0,0 +1,1793 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkBindingSet: Keybinding manager for GObjects.
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdarg.h>
+
+#include "gtkbindingsprivate.h"
+#include "gtkkeyhash.h"
+#include "gtkstylecontext.h"
+#include "gtkwidget.h"
+#include "gtkintl.h"
+
+/**
+ * SECTION:gtkbindings
+ * @Title: Bindings
+ * @Short_description: Key bindings for individual widgets
+ * @See_also: Keyboard Accelerators, Mnemonics, #GtkCssProvider
+ *
+ * #GtkBindingSet provides a mechanism for configuring GTK+ key bindings
+ * through CSS files. This eases key binding adjustments for application
+ * developers as well as users and provides GTK+ users or administrators
+ * with high key  binding configurability which requires no application
+ * or toolkit side changes.
+ *
+ * In order for bindings to work in a custom widget implementation, the
+ * widget’s #GtkWidget:can-focus and #GtkWidget:has-focus properties
+ * must both be true. For example, by calling gtk_widget_set_can_focus()
+ * in the widget’s initialisation function; and by calling
+ * gtk_widget_grab_focus() when the widget is clicked.
+ */
+
+/* --- defines --- */
+#define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK)
+
+
+/* --- structures --- */
+typedef enum {
+  GTK_BINDING_TOKEN_BIND,
+  GTK_BINDING_TOKEN_UNBIND
+} GtkBindingTokens;
+
+typedef struct _GtkBindingEntry  GtkBindingEntry;
+typedef struct _GtkBindingSignal GtkBindingSignal;
+typedef struct _GtkBindingArg    GtkBindingArg;
+typedef struct _GtkBindingSignalSignal   GtkBindingSignalSignal;
+typedef struct _GtkBindingSignalAction   GtkBindingSignalAction;
+typedef struct _GtkBindingSignalCallback GtkBindingSignalCallback;
+
+/**
+ * GtkBindingSet:
+ * @set_name: unique name of this binding set
+ * @priority: unused
+ * @entries: the key binding entries in this binding set
+ * @current: implementation detail
+ *
+ * A binding set maintains a list of activatable key bindings.
+ * A single binding set can match multiple types of widgets.
+ * Similar to style contexts, can be matched by any information contained
+ * in a widgets #GtkWidgetPath. When a binding within a set is matched upon
+ * activation, an action signal is emitted on the target widget to carry out
+ * the actual activation.
+ */
+struct _GtkBindingSet
+{
+  gchar           *set_name;
+  gint             priority;
+  GtkBindingEntry *entries;
+  GtkBindingEntry *current;
+};
+
+/**
+ * GtkBindingEntry:
+ * @keyval: key value to match
+ * @modifiers: key modifiers to match
+ * @binding_set: binding set this entry belongs to
+ * @destroyed: implementation detail
+ * @in_emission: implementation detail
+ * @marks_unbound: implementation detail
+ * @set_next: linked list of entries maintained by binding set
+ * @hash_next: implementation detail
+ * @signals: action signals of this entry
+ *
+ * Each key binding element of a binding sets binding list is
+ * represented by a GtkBindingEntry.
+ */
+struct _GtkBindingEntry
+{
+  /* key portion */
+  guint             keyval;
+  GdkModifierType   modifiers;
+
+  GtkBindingSet    *binding_set;
+  guint             destroyed     : 1;
+  guint             in_emission   : 1;
+  guint             marks_unbound : 1;
+  GtkBindingEntry  *set_next;
+  GtkBindingEntry  *hash_next;
+  GtkBindingSignal *signals;
+};
+
+/**
+ * GtkBindingArg:
+ * @arg_type: implementation detail
+ *
+ * A #GtkBindingArg holds the data associated with
+ * an argument for a key binding signal emission as
+ * stored in #GtkBindingSignal.
+ */
+struct _GtkBindingArg
+{
+  GType      arg_type;
+  union {
+    glong    long_data;
+    gdouble  double_data;
+    gchar   *string_data;
+  } d;
+};
+
+typedef enum 
+{
+  GTK_BINDING_SIGNAL,
+  GTK_BINDING_ACTION,
+  GTK_BINDING_CALLBACK
+} GtkBindingActionType;
+
+/**
+ * GtkBindingSignal:
+ * @next: implementation detail
+ * @action_type: Actual type of the action
+ *
+ * A GtkBindingSignal stores the necessary information to
+ * activate a widget in response to a key press via a signal
+ * emission.
+ */
+struct _GtkBindingSignal
+{
+  GtkBindingSignal     *next;
+  GtkBindingActionType  action_type;
+};
+
+struct _GtkBindingSignalSignal
+{
+  GtkBindingSignal  parent;
+  const gchar      *signal_name;
+  guint             n_args;
+  GtkBindingArg    *args;
+};
+
+struct _GtkBindingSignalAction
+{
+  GtkBindingSignal  parent;
+  const gchar      *action_name;
+  GVariant         *variant;
+};
+
+struct _GtkBindingSignalCallback
+{
+  GtkBindingSignal    parent;
+  GtkBindingCallback  callback;
+  GVariant           *args;
+  gpointer            user_data;
+  GDestroyNotify      user_destroy;
+};
+
+/* --- variables --- */
+static GHashTable       *binding_entry_hash_table = NULL;
+static GSList           *binding_key_hashes = NULL;
+static GSList           *binding_set_list = NULL;
+static const gchar       key_class_binding_set[] = "gtk-class-binding-set";
+static GQuark            key_id_class_binding_set = 0;
+
+
+/* --- functions --- */
+
+static GtkBindingSignal*
+binding_signal_new_signal (const gchar *signal_name,
+                           guint        n_args)
+{
+  GtkBindingSignalSignal *signal;
+
+  signal = (GtkBindingSignalSignal *) g_slice_alloc0 (sizeof (GtkBindingSignalSignal) + n_args * sizeof (GtkBindingArg));
+  signal->parent.next = NULL;
+  signal->parent.action_type = GTK_BINDING_SIGNAL;
+  signal->signal_name = g_intern_string (signal_name);
+  signal->n_args = n_args;
+  signal->args = (GtkBindingArg *)(signal + 1);
+
+  return &signal->parent;
+}
+
+static GtkBindingSignal*
+binding_signal_new_action (const gchar *action_name,
+                           GVariant    *variant)
+{
+  GtkBindingSignalAction *signal;
+
+  signal = g_slice_new0 (GtkBindingSignalAction);
+  signal->parent.next = NULL;
+  signal->parent.action_type = GTK_BINDING_ACTION;
+  signal->action_name = g_intern_string (action_name);
+  signal->variant = variant;
+  if (variant)
+    g_variant_ref_sink (variant);
+
+  return &signal->parent;
+}
+
+static GtkBindingSignal *
+binding_signal_new_callback (GtkBindingCallback  callback,
+                             GVariant           *args,
+                             gpointer            user_data,
+                             GDestroyNotify      user_destroy)
+{
+  GtkBindingSignalCallback *signal;
+
+  signal = g_slice_new0 (GtkBindingSignalCallback);
+  signal->parent.next = NULL;
+  signal->parent.action_type = GTK_BINDING_CALLBACK;
+  signal->callback = callback;
+  signal->args = args;
+  if (args)
+    g_variant_ref_sink (args);
+  signal->user_data = user_data;
+  signal->user_destroy = user_destroy;
+
+  return &signal->parent;
+}
+
+static void
+binding_signal_free (GtkBindingSignal *signal)
+{
+  guint i;
+
+  switch (signal->action_type)
+    {
+    case GTK_BINDING_SIGNAL:
+      {
+        GtkBindingSignalSignal *sig = (GtkBindingSignalSignal *) signal;
+        for (i = 0; i < sig->n_args; i++)
+          {
+            if (G_TYPE_FUNDAMENTAL (sig->args[i].arg_type) == G_TYPE_STRING)
+              g_free (sig->args[i].d.string_data);
+          }
+        g_slice_free1 (sizeof (GtkBindingSignalSignal) + sig->n_args * sizeof (GtkBindingArg), sig);
+      }
+      break;
+
+    case GTK_BINDING_ACTION:
+      {
+        GtkBindingSignalAction *sig = (GtkBindingSignalAction *) signal;
+        g_clear_pointer (&sig->variant, g_variant_unref);
+        g_slice_free (GtkBindingSignalAction, sig);
+      }
+      break;
+
+    case GTK_BINDING_CALLBACK:
+      {
+        GtkBindingSignalCallback *sig = (GtkBindingSignalCallback *) signal;
+        if (sig->user_destroy)
+          sig->user_destroy (sig->user_data);
+        g_slice_free (GtkBindingSignalCallback, sig);
+      }
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+}
+
+static guint
+binding_entry_hash (gconstpointer  key)
+{
+  register const GtkBindingEntry *e = key;
+  register guint h;
+
+  h = e->keyval;
+  h ^= e->modifiers;
+
+  return h;
+}
+
+static gint
+binding_entries_compare (gconstpointer  a,
+                         gconstpointer  b)
+{
+  register const GtkBindingEntry *ea = a;
+  register const GtkBindingEntry *eb = b;
+
+  return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
+}
+
+static void
+binding_key_hash_insert_entry (GtkKeyHash      *key_hash,
+                               GtkBindingEntry *entry)
+{
+  guint keyval = entry->keyval;
+
+  /* We store lowercased accelerators. To deal with this, if <Shift>
+   * was specified, uppercase.
+   */
+  if (entry->modifiers & GDK_SHIFT_MASK)
+    {
+      if (keyval == GDK_KEY_Tab)
+        keyval = GDK_KEY_ISO_Left_Tab;
+      else
+        keyval = gdk_keyval_to_upper (keyval);
+    }
+
+  _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry);
+}
+
+static void
+binding_key_hash_destroy (gpointer data)
+{
+  GtkKeyHash *key_hash = data;
+
+  binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash);
+  _gtk_key_hash_free (key_hash);
+}
+
+static void
+insert_entries_into_key_hash (gpointer key,
+                              gpointer value,
+                              gpointer data)
+{
+  GtkKeyHash *key_hash = data;
+  GtkBindingEntry *entry = value;
+
+  for (; entry; entry = entry->hash_next)
+    binding_key_hash_insert_entry (key_hash, entry);
+}
+
+static GtkKeyHash *
+binding_key_hash_for_keymap (GdkKeymap *keymap)
+{
+  static GQuark key_hash_quark = 0;
+  GtkKeyHash *key_hash;
+
+  if (!key_hash_quark)
+    key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash");
+
+  key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark);
+
+  if (!key_hash)
+    {
+      key_hash = _gtk_key_hash_new (keymap, NULL);
+      g_object_set_qdata_full (G_OBJECT (keymap), key_hash_quark, key_hash, binding_key_hash_destroy);
+
+      if (binding_entry_hash_table)
+        g_hash_table_foreach (binding_entry_hash_table,
+                              insert_entries_into_key_hash,
+                              key_hash);
+
+      binding_key_hashes = g_slist_prepend (binding_key_hashes, key_hash);
+    }
+
+  return key_hash;
+}
+
+
+static GtkBindingEntry*
+binding_entry_new (GtkBindingSet  *binding_set,
+                   guint           keyval,
+                   GdkModifierType modifiers)
+{
+  GSList *tmp_list;
+  GtkBindingEntry *entry;
+
+  if (!binding_entry_hash_table)
+    binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare);
+
+  entry = g_new (GtkBindingEntry, 1);
+  entry->keyval = keyval;
+  entry->modifiers = modifiers;
+  entry->binding_set = binding_set,
+  entry->destroyed = FALSE;
+  entry->in_emission = FALSE;
+  entry->marks_unbound = FALSE;
+  entry->signals = NULL;
+
+  entry->set_next = binding_set->entries;
+  binding_set->entries = entry;
+
+  entry->hash_next = g_hash_table_lookup (binding_entry_hash_table, entry);
+  if (entry->hash_next)
+    g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
+  g_hash_table_insert (binding_entry_hash_table, entry, entry);
+
+  for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
+    {
+      GtkKeyHash *key_hash = tmp_list->data;
+      binding_key_hash_insert_entry (key_hash, entry);
+    }
+
+  return entry;
+}
+
+static void
+binding_entry_free (GtkBindingEntry *entry)
+{
+  GtkBindingSignal *sig;
+
+  g_assert (entry->set_next == NULL &&
+            entry->hash_next == NULL &&
+            entry->in_emission == FALSE &&
+            entry->destroyed == TRUE);
+
+  entry->destroyed = FALSE;
+
+  sig = entry->signals;
+  while (sig)
+    {
+      GtkBindingSignal *prev;
+
+      prev = sig;
+      sig = prev->next;
+      binding_signal_free (prev);
+    }
+  g_free (entry);
+}
+
+static void
+binding_entry_destroy (GtkBindingEntry *entry)
+{
+  GtkBindingEntry *o_entry;
+  register GtkBindingEntry *tmp;
+  GtkBindingEntry *begin;
+  register GtkBindingEntry *last;
+  GSList *tmp_list;
+
+  /* unlink from binding set
+   */
+  last = NULL;
+  tmp = entry->binding_set->entries;
+  while (tmp)
+    {
+      if (tmp == entry)
+        {
+          if (last)
+            last->set_next = entry->set_next;
+          else
+            entry->binding_set->entries = entry->set_next;
+          break;
+        }
+      last = tmp;
+      tmp = last->set_next;
+    }
+  entry->set_next = NULL;
+
+  o_entry = g_hash_table_lookup (binding_entry_hash_table, entry);
+  begin = o_entry;
+  last = NULL;
+  tmp = begin;
+  while (tmp)
+    {
+      if (tmp == entry)
+        {
+          if (last)
+            last->hash_next = entry->hash_next;
+          else
+            begin = entry->hash_next;
+          break;
+        }
+      last = tmp;
+      tmp = last->hash_next;
+    }
+  entry->hash_next = NULL;
+
+  if (!begin)
+    g_hash_table_remove (binding_entry_hash_table, entry);
+  else if (begin != o_entry)
+    {
+      g_hash_table_remove (binding_entry_hash_table, entry);
+      g_hash_table_insert (binding_entry_hash_table, begin, begin);
+    }
+
+  for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
+    {
+      GtkKeyHash *key_hash = tmp_list->data;
+      _gtk_key_hash_remove_entry (key_hash, entry);
+    }
+
+  entry->destroyed = TRUE;
+
+  if (!entry->in_emission)
+    binding_entry_free (entry);
+}
+
+static GtkBindingEntry*
+binding_ht_lookup_entry (GtkBindingSet  *set,
+                         guint           keyval,
+                         GdkModifierType modifiers)
+{
+  GtkBindingEntry lookup_entry = { 0 };
+  GtkBindingEntry *entry;
+
+  if (!binding_entry_hash_table)
+    return NULL;
+
+  lookup_entry.keyval = keyval;
+  lookup_entry.modifiers = modifiers;
+
+  entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
+  for (; entry; entry = entry->hash_next)
+    if (entry->binding_set == set)
+      return entry;
+
+  return NULL;
+}
+
+static gboolean
+binding_compose_params (GObject         *object,
+                        GtkBindingArg   *args,
+                        GSignalQuery    *query,
+                        GValue         **params_p)
+{
+  GValue *params;
+  const GType *types;
+  guint i;
+  gboolean valid;
+
+  params = g_new0 (GValue, query->n_params + 1);
+  *params_p = params;
+
+  /* The instance we emit on is the first object in the array
+   */
+  g_value_init (params, G_TYPE_OBJECT);
+  g_value_set_object (params, G_OBJECT (object));
+  params++;
+
+  types = query->param_types;
+  valid = TRUE;
+  for (i = 1; i < query->n_params + 1 && valid; i++)
+    {
+      GValue tmp_value = G_VALUE_INIT;
+
+      g_value_init (params, *types);
+
+      switch (G_TYPE_FUNDAMENTAL (args->arg_type))
+        {
+        case G_TYPE_DOUBLE:
+          g_value_init (&tmp_value, G_TYPE_DOUBLE);
+          g_value_set_double (&tmp_value, args->d.double_data);
+          break;
+        case G_TYPE_LONG:
+          g_value_init (&tmp_value, G_TYPE_LONG);
+          g_value_set_long (&tmp_value, args->d.long_data);
+          break;
+        case G_TYPE_STRING:
+          /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
+           * that since we don't have a GParamSpec, so just do something simple
+           */
+          if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
+            {
+              GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
+              GEnumValue *enum_value;
+
+              valid = FALSE;
+
+              enum_value = g_enum_get_value_by_name (class, args->d.string_data);
+              if (!enum_value)
+                enum_value = g_enum_get_value_by_nick (class, args->d.string_data);
+
+              if (enum_value)
+                {
+                  g_value_init (&tmp_value, *types);
+                  g_value_set_enum (&tmp_value, enum_value->value);
+                  valid = TRUE;
+                }
+
+              g_type_class_unref (class);
+            }
+          /* This is just a hack for compatibility with GTK+-1.2 where a string
+           * could be used for a single flag value / without the support for multiple
+           * values in gtk_rc_parse_flags(), this isn't very useful.
+           */
+          else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
+            {
+              GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
+              GFlagsValue *flags_value;
+
+              valid = FALSE;
+
+              flags_value = g_flags_get_value_by_name (class, args->d.string_data);
+              if (!flags_value)
+                flags_value = g_flags_get_value_by_nick (class, args->d.string_data);
+              if (flags_value)
+                {
+                  g_value_init (&tmp_value, *types);
+                  g_value_set_flags (&tmp_value, flags_value->value);
+                  valid = TRUE;
+                }
+
+              g_type_class_unref (class);
+            }
+          else
+            {
+              g_value_init (&tmp_value, G_TYPE_STRING);
+              g_value_set_static_string (&tmp_value, args->d.string_data);
+            }
+          break;
+        default:
+          valid = FALSE;
+          break;
+        }
+
+      if (valid)
+        {
+          if (!g_value_transform (&tmp_value, params))
+            valid = FALSE;
+
+          g_value_unset (&tmp_value);
+        }
+
+      types++;
+      params++;
+      args++;
+    }
+
+  if (!valid)
+    {
+      guint j;
+
+      for (j = 0; j < i; j++)
+        g_value_unset (&(*params_p)[j]);
+
+      g_free (*params_p);
+      *params_p = NULL;
+    }
+
+  return valid;
+}
+
+static gboolean
+binding_signal_activate_signal (GtkBindingSignalSignal *sig,
+                                GObject                *object)
+{
+  GSignalQuery query;
+  guint signal_id;
+  GValue *params = NULL;
+  GValue return_val = G_VALUE_INIT;
+  gboolean handled = FALSE;
+
+  signal_id = g_signal_lookup (sig->signal_name, G_OBJECT_TYPE (object));
+  if (!signal_id)
+    {
+      g_warning ("gtk_binding_entry_activate(): "
+                 "could not find signal \"%s\" in the '%s' class ancestry",
+                 sig->signal_name,
+                 g_type_name (G_OBJECT_TYPE (object)));
+      return FALSE;
+    }
+
+  g_signal_query (signal_id, &query);
+  if (query.n_params != sig->n_args ||
+      (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) ||
+      !binding_compose_params (object, sig->args, &query, &params))
+    {
+      g_warning ("gtk_binding_entry_activate(): "
+                 "signature mismatch for signal \"%s\" in the '%s' class ancestry",
+                 sig->signal_name,
+                 g_type_name (G_OBJECT_TYPE (object)));
+      return FALSE;
+    }
+  else if (!(query.signal_flags & G_SIGNAL_ACTION))
+    {
+      g_warning ("gtk_binding_entry_activate(): "
+                 "signal \"%s\" in the '%s' class ancestry cannot be used for action emissions",
+                 sig->signal_name,
+                 g_type_name (G_OBJECT_TYPE (object)));
+      return FALSE;
+    }
+
+  if (query.return_type == G_TYPE_BOOLEAN)
+    g_value_init (&return_val, G_TYPE_BOOLEAN);
+
+  g_signal_emitv (params, signal_id, 0, &return_val);
+
+  if (query.return_type == G_TYPE_BOOLEAN)
+    {
+      if (g_value_get_boolean (&return_val))
+        handled = TRUE;
+      g_value_unset (&return_val);
+    }
+  else
+    handled = TRUE;
+
+  if (params != NULL)
+    {
+      guint i;
+
+      for (i = 0; i < query.n_params + 1; i++)
+        g_value_unset (&params[i]);
+
+      g_free (params);
+    }
+
+  return handled;
+}
+
+static gboolean
+binding_signal_activate_action (GtkBindingSignalAction *sig,
+                                GObject                *object)
+{
+  if (!GTK_IS_WIDGET (object))
+    {
+      g_warning ("gtk_binding_entry_activate(): "
+                 "actions must be emitted on GtkWidget subtypes, %s is not supported",
+                 G_OBJECT_TYPE_NAME (object));
+      return FALSE;
+    }
+
+  if (!gtk_widget_activate_action_variant (GTK_WIDGET (object), sig->action_name, sig->variant))
+    {
+      g_warning ("gtk_binding_entry_activate(): "
+                 "action \"%s\" does not exist on class \"%s\"",
+                 sig->action_name,
+                 G_OBJECT_TYPE_NAME (object));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+binding_signal_activate_callback (GtkBindingSignalCallback *sig,
+                                  GObject                  *object)
+{
+  if (!GTK_IS_WIDGET (object))
+    {
+      g_warning ("gtk_binding_entry_activate(): "
+                 "callbacks must be run on GtkWidget subtypes, %s is not supported",
+                 G_OBJECT_TYPE_NAME (object));
+      return FALSE;
+    }
+
+  sig->callback (GTK_WIDGET (object), sig->args, sig->user_data);
+
+  return TRUE;
+}
+
+static gboolean
+gtk_binding_entry_activate (GtkBindingEntry *entry,
+                            GObject         *object)
+{
+  GtkBindingSignal *sig;
+  gboolean old_emission;
+  gboolean handled = FALSE;
+
+  old_emission = entry->in_emission;
+  entry->in_emission = TRUE;
+
+  g_object_ref (object);
+
+  for (sig = entry->signals; sig; sig = sig->next)
+    {
+      switch (sig->action_type)
+        {
+        case GTK_BINDING_SIGNAL:
+          handled = binding_signal_activate_signal ((GtkBindingSignalSignal *) sig, object);
+          break;
+
+        case GTK_BINDING_ACTION:
+          handled = binding_signal_activate_action ((GtkBindingSignalAction *) sig, object);
+          break;
+
+        case GTK_BINDING_CALLBACK:
+          handled = binding_signal_activate_callback ((GtkBindingSignalCallback *) sig, object);
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+
+      if (entry->destroyed)
+        break;
+    }
+
+  g_object_unref (object);
+
+  entry->in_emission = old_emission;
+  if (entry->destroyed && !entry->in_emission)
+    binding_entry_free (entry);
+
+  return handled;
+}
+
+/**
+ * gtk_binding_set_new: (skip)
+ * @set_name: unique name of this binding set
+ *
+ * GTK+ maintains a global list of binding sets. Each binding set has
+ * a unique name which needs to be specified upon creation.
+ *
+ * Returns: (transfer none): new binding set
+ */
+GtkBindingSet*
+gtk_binding_set_new (const gchar *set_name)
+{
+  GtkBindingSet *binding_set;
+
+  g_return_val_if_fail (set_name != NULL, NULL);
+
+  binding_set = g_new (GtkBindingSet, 1);
+  binding_set->set_name = (gchar *) g_intern_string (set_name);
+  binding_set->entries = NULL;
+  binding_set->current = NULL;
+
+  binding_set_list = g_slist_prepend (binding_set_list, binding_set);
+
+  return binding_set;
+}
+
+/**
+ * gtk_binding_set_by_class: (skip)
+ * @object_class: a valid #GObject class
+ *
+ * This function returns the binding set named after the type name of
+ * the passed in class structure. New binding sets are created on
+ * demand by this function.
+ *
+ * Returns: (transfer none): the binding set corresponding to
+ *     @object_class
+ */
+GtkBindingSet*
+gtk_binding_set_by_class (gpointer object_class)
+{
+  GObjectClass *class = object_class;
+  GtkBindingSet* binding_set;
+
+  g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
+
+  if (!key_id_class_binding_set)
+    key_id_class_binding_set = g_quark_from_static_string (key_class_binding_set);
+
+  binding_set = g_dataset_id_get_data (class, key_id_class_binding_set);
+
+  if (binding_set)
+    return binding_set;
+
+  binding_set = gtk_binding_set_new (g_type_name (G_OBJECT_CLASS_TYPE (class)));
+  g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
+
+  return binding_set;
+}
+
+static GtkBindingSet*
+gtk_binding_set_find_interned (const gchar *set_name)
+{
+  GSList *slist;
+
+  for (slist = binding_set_list; slist; slist = slist->next)
+    {
+      GtkBindingSet *binding_set;
+
+      binding_set = slist->data;
+      if (binding_set->set_name == set_name)
+        return binding_set;
+    }
+
+  return NULL;
+}
+
+/**
+ * gtk_binding_set_find:
+ * @set_name: unique binding set name
+ *
+ * Find a binding set by its globally unique name.
+ *
+ * The @set_name can either be a name used for gtk_binding_set_new()
+ * or the type name of a class used in gtk_binding_set_by_class().
+ *
+ * Returns: (nullable) (transfer none): %NULL or the specified binding set
+ */
+GtkBindingSet*
+gtk_binding_set_find (const gchar *set_name)
+{
+  g_return_val_if_fail (set_name != NULL, NULL);
+
+  return gtk_binding_set_find_interned (g_intern_string (set_name));
+}
+
+/**
+ * gtk_binding_set_activate:
+ * @binding_set: a #GtkBindingSet set to activate
+ * @keyval:      key value of the binding
+ * @modifiers:   key modifier of the binding
+ * @object:      object to activate when binding found
+ *
+ * Find a key binding matching @keyval and @modifiers within
+ * @binding_set and activate the binding on @object.
+ *
+ * Returns: %TRUE if a binding was found and activated
+ */
+gboolean
+gtk_binding_set_activate (GtkBindingSet  *binding_set,
+                          guint           keyval,
+                          GdkModifierType modifiers,
+                          GObject        *object)
+{
+  GtkBindingEntry *entry;
+
+  g_return_val_if_fail (binding_set != NULL, FALSE);
+  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+  keyval = gdk_keyval_to_lower (keyval);
+  modifiers = modifiers & BINDING_MOD_MASK ();
+
+  entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+  if (entry)
+    return gtk_binding_entry_activate (entry, object);
+
+  return FALSE;
+}
+
+static void
+gtk_binding_entry_clear_internal (GtkBindingSet  *binding_set,
+                                  guint           keyval,
+                                  GdkModifierType modifiers)
+{
+  GtkBindingEntry *entry;
+
+  keyval = gdk_keyval_to_lower (keyval);
+  modifiers = modifiers & BINDING_MOD_MASK ();
+
+  entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+  if (entry)
+    binding_entry_destroy (entry);
+
+  entry = binding_entry_new (binding_set, keyval, modifiers);
+}
+
+/**
+ * gtk_binding_entry_skip:
+ * @binding_set: a #GtkBindingSet to skip an entry of
+ * @keyval:      key value of binding to skip
+ * @modifiers:   key modifier of binding to skip
+ *
+ * Install a binding on @binding_set which causes key lookups
+ * to be aborted, to prevent bindings from lower priority sets
+ * to be activated.
+ */
+void
+gtk_binding_entry_skip (GtkBindingSet  *binding_set,
+                        guint           keyval,
+                        GdkModifierType modifiers)
+{
+  GtkBindingEntry *entry;
+
+  g_return_if_fail (binding_set != NULL);
+
+  keyval = gdk_keyval_to_lower (keyval);
+  modifiers = modifiers & BINDING_MOD_MASK ();
+
+  entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+  if (entry)
+    binding_entry_destroy (entry);
+
+  entry = binding_entry_new (binding_set, keyval, modifiers);
+  entry->marks_unbound = TRUE;
+}
+
+/**
+ * gtk_binding_entry_remove:
+ * @binding_set: a #GtkBindingSet to remove an entry of
+ * @keyval:      key value of binding to remove
+ * @modifiers:   key modifier of binding to remove
+ *
+ * Remove a binding previously installed via
+ * gtk_binding_entry_add_signal() on @binding_set.
+ */
+void
+gtk_binding_entry_remove (GtkBindingSet  *binding_set,
+                          guint           keyval,
+                          GdkModifierType modifiers)
+{
+  GtkBindingEntry *entry;
+
+  g_return_if_fail (binding_set != NULL);
+
+  keyval = gdk_keyval_to_lower (keyval);
+  modifiers = modifiers & BINDING_MOD_MASK ();
+
+  entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+  if (entry)
+    binding_entry_destroy (entry);
+}
+
+static void
+gtk_binding_entry_add_binding_signal (GtkBindingSet    *binding_set,
+                                      guint             keyval,
+                                      GdkModifierType   modifiers,
+                                      GtkBindingSignal *signal)
+{
+  GtkBindingEntry *entry;
+  GtkBindingSignal **signal_p;
+
+  keyval = gdk_keyval_to_lower (keyval);
+  modifiers = modifiers & BINDING_MOD_MASK ();
+
+  entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+  if (!entry)
+    {
+      gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
+      entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+    }
+  signal_p = &entry->signals;
+  while (*signal_p)
+    signal_p = &(*signal_p)->next;
+  *signal_p = signal;
+}
+
+/*
+ * gtk_binding_entry_add_signall:
+ * @binding_set:  a #GtkBindingSet to add a signal to
+ * @keyval:       key value
+ * @modifiers:    key modifier
+ * @signal_name:  signal name to be bound
+ * @binding_args: (transfer none) (element-type GtkBindingArg):
+ *     list of #GtkBindingArg signal arguments
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set.
+ */
+static void
+gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
+                               guint           keyval,
+                               GdkModifierType modifiers,
+                               const gchar    *signal_name,
+                               GSList         *binding_args)
+{
+  GtkBindingSignal *signal;
+  GSList *slist;
+  guint n = 0;
+  GtkBindingArg *arg;
+
+  g_return_if_fail (binding_set != NULL);
+  g_return_if_fail (signal_name != NULL);
+
+  signal = binding_signal_new_signal (signal_name, g_slist_length (binding_args));
+
+  arg = ((GtkBindingSignalSignal *) signal)->args;
+  for (slist = binding_args; slist; slist = slist->next)
+    {
+      GtkBindingArg *tmp_arg;
+
+      tmp_arg = slist->data;
+      if (!tmp_arg)
+        {
+          g_warning ("gtk_binding_entry_add_signall(): arg[%u] is 'NULL'", n);
+          binding_signal_free (signal);
+          return;
+        }
+      switch (G_TYPE_FUNDAMENTAL (tmp_arg->arg_type))
+        {
+        case  G_TYPE_LONG:
+          arg->arg_type = G_TYPE_LONG;
+          arg->d.long_data = tmp_arg->d.long_data;
+          break;
+        case  G_TYPE_DOUBLE:
+          arg->arg_type = G_TYPE_DOUBLE;
+          arg->d.double_data = tmp_arg->d.double_data;
+          break;
+        case  G_TYPE_STRING:
+          arg->arg_type = G_TYPE_STRING;
+          arg->d.string_data = g_strdup (tmp_arg->d.string_data);
+          if (!arg->d.string_data)
+            {
+              g_warning ("gtk_binding_entry_add_signall(): value of 'string' arg[%u] is 'NULL'", n);
+              binding_signal_free (signal);
+              return;
+            }
+          break;
+        default:
+          g_warning ("gtk_binding_entry_add_signall(): unsupported type '%s' for arg[%u]",
+                     g_type_name (arg->arg_type), n);
+          binding_signal_free (signal);
+          return;
+        }
+      arg++;
+      n++;
+    }
+
+  gtk_binding_entry_add_binding_signal (binding_set, keyval, modifiers, signal);
+}
+
+/**
+ * gtk_binding_entry_add_signal:
+ * @binding_set: a #GtkBindingSet to install an entry for
+ * @keyval:      key value of binding to install
+ * @modifiers:   key modifier of binding to install
+ * @signal_name: signal to execute upon activation
+ * @n_args:      number of arguments to @signal_name
+ * @...:         arguments to @signal_name
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set. When the binding is activated, @signal_name will be
+ * emitted on the target widget, with @n_args @Varargs used as
+ * arguments.
+ *
+ * Each argument to the signal must be passed as a pair of varargs: the
+ * #GType of the argument, followed by the argument value (which must
+ * be of the given type). There must be @n_args pairs in total.
+ *
+ * ## Adding a Key Binding
+ *
+ * |[<!-- language="C" -->
+ * GtkBindingSet *binding_set;
+ * GdkModifierType modmask = GDK_CONTROL_MASK;
+ * int count = 1;
+ * gtk_binding_entry_add_signal (binding_set,
+ *                               GDK_KEY_space,
+ *                               modmask,
+ *                               "move-cursor", 2,
+ *                               GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_PAGES,
+ *                               G_TYPE_INT, count,
+ *                               G_TYPE_BOOLEAN, FALSE);
+ * ]|
+ */
+void
+gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
+                              guint           keyval,
+                              GdkModifierType modifiers,
+                              const gchar    *signal_name,
+                              guint           n_args,
+                              ...)
+{
+  GSList *slist, *free_slist;
+  va_list args;
+  guint i;
+
+  g_return_if_fail (binding_set != NULL);
+  g_return_if_fail (signal_name != NULL);
+
+  va_start (args, n_args);
+  slist = NULL;
+  for (i = 0; i < n_args; i++)
+    {
+      GtkBindingArg *arg;
+
+      arg = g_slice_new0 (GtkBindingArg);
+      slist = g_slist_prepend (slist, arg);
+
+      arg->arg_type = va_arg (args, GType);
+      switch (G_TYPE_FUNDAMENTAL (arg->arg_type))
+        {
+        case G_TYPE_CHAR:
+        case G_TYPE_UCHAR:
+        case G_TYPE_INT:
+        case G_TYPE_UINT:
+        case G_TYPE_BOOLEAN:
+        case G_TYPE_ENUM:
+        case G_TYPE_FLAGS:
+          arg->arg_type = G_TYPE_LONG;
+          arg->d.long_data = va_arg (args, gint);
+          break;
+        case G_TYPE_LONG:
+        case G_TYPE_ULONG:
+          arg->arg_type = G_TYPE_LONG;
+          arg->d.long_data = va_arg (args, glong);
+          break;
+        case G_TYPE_FLOAT:
+        case G_TYPE_DOUBLE:
+          arg->arg_type = G_TYPE_DOUBLE;
+          arg->d.double_data = va_arg (args, gdouble);
+          break;
+        case G_TYPE_STRING:
+          arg->arg_type = G_TYPE_STRING;
+          arg->d.string_data = va_arg (args, gchar*);
+          if (!arg->d.string_data)
+            {
+              g_warning ("gtk_binding_entry_add_signal(): type '%s' arg[%u] is 'NULL'",
+                         g_type_name (arg->arg_type),
+                         i);
+              i += n_args + 1;
+            }
+          break;
+        default:
+          g_warning ("gtk_binding_entry_add_signal(): unsupported type '%s' for arg[%u]",
+                     g_type_name (arg->arg_type), i);
+          i += n_args + 1;
+          break;
+        }
+    }
+  va_end (args);
+
+  if (i == n_args || i == 0)
+    {
+      slist = g_slist_reverse (slist);
+      gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
+    }
+
+  free_slist = slist;
+  while (slist)
+    {
+      g_slice_free (GtkBindingArg, slist->data);
+      slist = slist->next;
+    }
+  g_slist_free (free_slist);
+}
+
+/**
+ * gtk_binding_entry_add_action_variant:
+ * @binding_set: a #GtkBindingSet to install an entry for
+ * @keyval:      key value of binding to install
+ * @modifiers:   key modifier of binding to install
+ * @action_name: signal to execute upon activation
+ * @args:        #GVariant of the arguments or %NULL if none
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set. When the binding is activated, @action_name will be
+ * activated on the target widget, with @args used as arguments.
+ */
+void
+gtk_binding_entry_add_action_variant (GtkBindingSet  *binding_set,
+                                      guint           keyval,
+                                      GdkModifierType modifiers,
+                                      const gchar    *action_name,
+                                      GVariant       *args)
+{
+  g_return_if_fail (binding_set != NULL);
+  g_return_if_fail (action_name != NULL);
+
+  gtk_binding_entry_add_binding_signal (binding_set,
+                                        keyval,
+                                        modifiers,
+                                        binding_signal_new_action (action_name, args));
+}
+
+/**
+ * gtk_binding_entry_add_action:
+ * @binding_set: a #GtkBindingSet to install an entry for
+ * @keyval:      key value of binding to install
+ * @modifiers:   key modifier of binding to install
+ * @action_name: signal to execute upon activation
+ * @format_string: GVariant format string for arguments or %NULL
+ *    for no arguments
+ * @...: arguments, as given by format string
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set. When the binding is activated, @action_name will be
+ * activated on the target widget, with arguments read according to
+ * @format_string.
+ */
+void
+gtk_binding_entry_add_action (GtkBindingSet  *binding_set,
+                              guint           keyval,
+                              GdkModifierType modifiers,
+                              const char     *action_name,
+                              const char     *format_string,
+                              ...)
+{
+  GVariant *parameters = NULL;
+
+  g_return_if_fail (binding_set != NULL);
+  g_return_if_fail (action_name != NULL);
+
+  if (format_string != NULL)
+    {
+      va_list args;
+
+      va_start (args, format_string);
+      parameters = g_variant_new_va (format_string, NULL, &args);
+      va_end (args);
+
+      g_variant_ref_sink (parameters);
+    }
+
+  gtk_binding_entry_add_action_variant (binding_set, keyval, modifiers, action_name, parameters);
+
+  g_clear_pointer (&parameters, g_variant_unref);
+}
+
+void
+gtk_binding_entry_add_callback (GtkBindingSet      *binding_set,
+                                guint               keyval,
+                                GdkModifierType     modifiers,
+                                GtkBindingCallback  callback,
+                                GVariant           *args,
+                                gpointer            user_data,
+                                GDestroyNotify      user_destroy)
+{
+  g_return_if_fail (binding_set != NULL);
+  g_return_if_fail (callback != NULL);
+
+  gtk_binding_entry_add_binding_signal (binding_set,
+                                        keyval,
+                                        modifiers,
+                                        binding_signal_new_callback (callback, args, user_data, user_destroy));
+
+}
+
+static guint
+gtk_binding_parse_signal (GScanner       *scanner,
+                          GtkBindingSet  *binding_set,
+                          guint           keyval,
+                          GdkModifierType modifiers)
+{
+  gchar *signal;
+  guint expected_token = 0;
+  GSList *args;
+  GSList *slist;
+  gboolean done;
+  gboolean negate;
+  gboolean need_arg;
+  gboolean seen_comma;
+
+  g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+
+  g_scanner_get_next_token (scanner);
+
+  if (scanner->token != G_TOKEN_STRING)
+    return G_TOKEN_STRING;
+
+  g_scanner_peek_next_token (scanner);
+
+  if (scanner->next_token != '(')
+    {
+      g_scanner_get_next_token (scanner);
+      return '(';
+    }
+
+  signal = g_strdup (scanner->value.v_string);
+  g_scanner_get_next_token (scanner);
+
+  negate = FALSE;
+  args = NULL;
+  done = FALSE;
+  need_arg = TRUE;
+  seen_comma = FALSE;
+  scanner->config->scan_symbols = FALSE;
+
+  do
+    {
+      GtkBindingArg *arg;
+
+      if (need_arg)
+        expected_token = G_TOKEN_INT;
+      else
+        expected_token = ')';
+
+      g_scanner_get_next_token (scanner);
+
+      switch ((guint) scanner->token)
+        {
+        case G_TOKEN_FLOAT:
+          if (need_arg)
+            {
+              need_arg = FALSE;
+              arg = g_new (GtkBindingArg, 1);
+              arg->arg_type = G_TYPE_DOUBLE;
+              arg->d.double_data = scanner->value.v_float;
+
+              if (negate)
+                {
+                  arg->d.double_data = - arg->d.double_data;
+                  negate = FALSE;
+                }
+              args = g_slist_prepend (args, arg);
+            }
+          else
+            done = TRUE;
+
+          break;
+        case G_TOKEN_INT:
+          if (need_arg)
+            {
+              need_arg = FALSE;
+              arg = g_new (GtkBindingArg, 1);
+              arg->arg_type = G_TYPE_LONG;
+              arg->d.long_data = scanner->value.v_int;
+
+              if (negate)
+                {
+                  arg->d.long_data = - arg->d.long_data;
+                  negate = FALSE;
+                }
+              args = g_slist_prepend (args, arg);
+            }
+          else
+            done = TRUE;
+          break;
+        case G_TOKEN_STRING:
+          if (need_arg && !negate)
+            {
+              need_arg = FALSE;
+              arg = g_new (GtkBindingArg, 1);
+              arg->arg_type = G_TYPE_STRING;
+              arg->d.string_data = g_strdup (scanner->value.v_string);
+              args = g_slist_prepend (args, arg);
+            }
+          else
+            done = TRUE;
+
+          break;
+        case G_TOKEN_IDENTIFIER:
+          if (need_arg && !negate)
+            {
+              need_arg = FALSE;
+              arg = g_new (GtkBindingArg, 1);
+              arg->arg_type = G_TYPE_STRING;
+              arg->d.string_data = g_strdup (scanner->value.v_identifier);
+              args = g_slist_prepend (args, arg);
+            }
+          else
+            done = TRUE;
+
+          break;
+        case '-':
+          if (!need_arg)
+            done = TRUE;
+          else if (negate)
+            {
+              expected_token = G_TOKEN_INT;
+              done = TRUE;
+            }
+          else
+            negate = TRUE;
+
+          break;
+        case ',':
+          seen_comma = TRUE;
+          if (need_arg)
+            done = TRUE;
+          else
+            need_arg = TRUE;
+
+          break;
+        case ')':
+          if (!(need_arg && seen_comma) && !negate)
+            {
+              args = g_slist_reverse (args);
+              gtk_binding_entry_add_signall (binding_set,
+                                             keyval,
+                                             modifiers,
+                                             signal,
+                                             args);
+              expected_token = G_TOKEN_NONE;
+            }
+
+          done = TRUE;
+          break;
+        default:
+          done = TRUE;
+          break;
+        }
+    }
+  while (!done);
+
+  scanner->config->scan_symbols = TRUE;
+
+  for (slist = args; slist; slist = slist->next)
+    {
+      GtkBindingArg *arg;
+
+      arg = slist->data;
+
+      if (G_TYPE_FUNDAMENTAL (arg->arg_type) == G_TYPE_STRING)
+        g_free (arg->d.string_data);
+      g_free (arg);
+    }
+
+  g_slist_free (args);
+  g_free (signal);
+
+  return expected_token;
+}
+
+static inline guint
+gtk_binding_parse_bind (GScanner       *scanner,
+                        GtkBindingSet  *binding_set)
+{
+  guint keyval = 0;
+  GdkModifierType modifiers = 0;
+  gboolean unbind = FALSE;
+
+  g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+
+  g_scanner_get_next_token (scanner);
+
+  if (scanner->token != G_TOKEN_SYMBOL)
+    return G_TOKEN_SYMBOL;
+
+  if (scanner->value.v_symbol != GUINT_TO_POINTER (GTK_BINDING_TOKEN_BIND) &&
+      scanner->value.v_symbol != GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND))
+    return G_TOKEN_SYMBOL;
+
+  unbind = (scanner->value.v_symbol == GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND));
+  g_scanner_get_next_token (scanner);
+
+  if (scanner->token != (guint) G_TOKEN_STRING)
+    return G_TOKEN_STRING;
+
+  gtk_accelerator_parse (scanner->value.v_string, &keyval, &modifiers);
+  modifiers &= BINDING_MOD_MASK ();
+
+  if (keyval == 0)
+    return G_TOKEN_STRING;
+
+  if (unbind)
+    {
+      gtk_binding_entry_skip (binding_set, keyval, modifiers);
+      return G_TOKEN_NONE;
+    }
+
+  g_scanner_get_next_token (scanner);
+
+  if (scanner->token != '{')
+    return '{';
+
+  gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
+  g_scanner_peek_next_token (scanner);
+
+  while (scanner->next_token != '}')
+    {
+      guint expected_token;
+
+      if (scanner->next_token == G_TOKEN_STRING)
+        {
+          expected_token = gtk_binding_parse_signal (scanner,
+                                                     binding_set,
+                                                     keyval,
+                                                     modifiers);
+          if (expected_token != G_TOKEN_NONE)
+            return expected_token;
+        }
+      else
+        {
+          g_scanner_get_next_token (scanner);
+          return '}';
+        }
+
+      g_scanner_peek_next_token (scanner);
+    }
+
+  g_scanner_get_next_token (scanner);
+
+  return G_TOKEN_NONE;
+}
+
+static GScanner *
+create_signal_scanner (void)
+{
+  GScanner *scanner;
+
+  scanner = g_scanner_new (NULL);
+  scanner->config->cset_identifier_nth = (char *) G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_";
+
+  g_scanner_scope_add_symbol (scanner, 0, "bind", GUINT_TO_POINTER (GTK_BINDING_TOKEN_BIND));
+  g_scanner_scope_add_symbol (scanner, 0, "unbind", GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND));
+
+  g_scanner_set_scope (scanner, 0);
+
+  return scanner;
+}
+
+/**
+ * gtk_binding_entry_add_signal_from_string:
+ * @binding_set: a #GtkBindingSet
+ * @signal_desc: a signal description
+ *
+ * Parses a signal description from @signal_desc and incorporates
+ * it into @binding_set.
+ *
+ * Signal descriptions may either bind a key combination to
+ * one or more signals:
+ * |[
+ *   bind "key" {
+ *     "signalname" (param, ...)
+ *     ...
+ *   }
+ * ]|
+ *
+ * Or they may also unbind a key combination:
+ * |[
+ *   unbind "key"
+ * ]|
+ *
+ * Key combinations must be in a format that can be parsed by
+ * gtk_accelerator_parse().
+ *
+ * Returns: %G_TOKEN_NONE if the signal was successfully parsed and added,
+ *     the expected token otherwise
+ */
+GTokenType
+gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
+                                          const gchar   *signal_desc)
+{
+  static GScanner *scanner = NULL;
+  GTokenType ret;
+
+  g_return_val_if_fail (binding_set != NULL, G_TOKEN_NONE);
+  g_return_val_if_fail (signal_desc != NULL, G_TOKEN_NONE);
+
+  if (G_UNLIKELY (!scanner))
+    scanner = create_signal_scanner ();
+
+  g_scanner_input_text (scanner, signal_desc,
+                        (guint) strlen (signal_desc));
+
+  ret = gtk_binding_parse_bind (scanner, binding_set);
+
+  /* Reset for next use */
+  g_scanner_set_scope (scanner, 0);
+
+  return ret;
+}
+
+static gint
+find_entry_with_binding (GtkBindingEntry *entry,
+                         GtkBindingSet   *binding_set)
+{
+  return (entry->binding_set == binding_set) ? 0 : 1;
+}
+
+static gboolean
+binding_activate (GtkBindingSet *binding_set,
+                  GSList        *entries,
+                  GObject       *object,
+                  gboolean       is_release,
+                  gboolean      *unbound)
+{
+  GtkBindingEntry *entry;
+  GSList *elem;
+
+  elem = g_slist_find_custom (entries, binding_set,
+                              (GCompareFunc) find_entry_with_binding);
+
+  if (!elem)
+    return FALSE;
+
+  entry = elem->data;
+
+  if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
+    return FALSE;
+
+  if (entry->marks_unbound)
+    {
+      *unbound = TRUE;
+      return FALSE;
+    }
+
+  if (gtk_binding_entry_activate (entry, object))
+    return TRUE;
+
+  return FALSE;
+}
+
+static gboolean
+gtk_bindings_activate_list (GObject  *object,
+                            GSList   *entries,
+                            gboolean  is_release)
+{
+  GtkBindingSet *binding_set;
+  gboolean handled = FALSE;
+  gboolean unbound = FALSE;
+
+  if (!entries)
+    return FALSE;
+
+  if (!handled)
+    {
+      GType class_type;
+
+      class_type = G_TYPE_FROM_INSTANCE (object);
+
+      while (class_type && !handled)
+        {
+          binding_set = gtk_binding_set_find_interned (g_type_name (class_type));
+          class_type = g_type_parent (class_type);
+
+          if (!binding_set)
+            continue;
+
+          handled = binding_activate (binding_set, entries,
+                                      object, is_release,
+                                      &unbound);
+          if (unbound)
+            break;
+        }
+
+      if (unbound)
+        return FALSE;
+    }
+
+  return handled;
+}
+
+/**
+ * gtk_bindings_activate:
+ * @object: object to activate when binding found
+ * @keyval: key value of the binding
+ * @modifiers: key modifier of the binding
+ *
+ * Find a key binding matching @keyval and @modifiers and activate the
+ * binding on @object.
+ *
+ * Returns: %TRUE if a binding was found and activated
+ */
+gboolean
+gtk_bindings_activate (GObject         *object,
+                       guint            keyval,
+                       GdkModifierType  modifiers)
+{
+  GSList *entries = NULL;
+  GdkDisplay *display;
+  GtkKeyHash *key_hash;
+  gboolean handled = FALSE;
+  gboolean is_release;
+
+  if (!GTK_IS_WIDGET (object))
+    return FALSE;
+
+  is_release = (modifiers & GDK_RELEASE_MASK) != 0;
+  modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
+
+  display = gtk_widget_get_display (GTK_WIDGET (object));
+  key_hash = binding_key_hash_for_keymap (gdk_display_get_keymap (display));
+
+  entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
+
+  handled = gtk_bindings_activate_list (object, entries, is_release);
+
+  g_slist_free (entries);
+
+  return handled;
+}
+
+/**
+ * gtk_bindings_activate_event:
+ * @object: a #GObject (generally must be a widget)
+ * @event: a key event
+ *
+ * Looks up key bindings for @object to find one matching
+ * @event, and if one was found, activate it.
+ *
+ * Returns: %TRUE if a matching key binding was found
+ */
+gboolean
+gtk_bindings_activate_event (GObject  *object,
+                             GdkEvent *event)
+{
+  GSList *entries = NULL;
+  GdkDisplay *display;
+  GtkKeyHash *key_hash;
+  gboolean handled = FALSE;
+
+  if (!GTK_IS_WIDGET (object))
+    return FALSE;
+
+  display = gtk_widget_get_display (GTK_WIDGET (object));
+  key_hash = binding_key_hash_for_keymap (gdk_display_get_keymap (display));
+
+  entries = _gtk_key_hash_lookup (key_hash,
+                                  gdk_key_event_get_keycode (event),
+                                  gdk_event_get_modifier_state (event),
+                                  BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
+                                  gdk_key_event_get_group(event));
+
+  handled = gtk_bindings_activate_list (object, entries,
+                                        gdk_event_get_event_type (event) == GDK_KEY_RELEASE);
+
+  g_slist_free (entries);
+
+  return handled;
+}
diff --git a/gtk/gtkbindings.h b/gtk/gtkbindings.h
new file mode 100644 (file)
index 0000000..ef8756f
--- /dev/null
@@ -0,0 +1,124 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkBindingSet: Keybinding manager for GObjects.
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __GTK_BINDINGS_H__
+#define __GTK_BINDINGS_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtktypes.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkBindingSet    GtkBindingSet;
+
+/**
+ * GtkBindingCallback:
+ * @widget: The object to invoke the callback on
+ * @args: (allow-none): The arguments or %NULL if none
+ * @user_data: The user data passed when registering the callback
+ *
+ * Prototype of the callback function registered with
+ * gtk_binding_entry_add_callback.
+ */
+typedef void   (* GtkBindingCallback)        (GtkWidget           *widget,
+                                              GVariant            *args,
+                                              gpointer             user_data);
+
+GDK_AVAILABLE_IN_ALL
+GtkBindingSet *gtk_binding_set_new           (const gchar         *set_name);
+GDK_AVAILABLE_IN_ALL
+GtkBindingSet *gtk_binding_set_by_class      (gpointer             object_class);
+GDK_AVAILABLE_IN_ALL
+GtkBindingSet *gtk_binding_set_find          (const gchar         *set_name);
+
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_bindings_activate         (GObject             *object,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers);
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_bindings_activate_event   (GObject             *object,
+                                              GdkEvent            *event);
+GDK_AVAILABLE_IN_ALL
+gboolean       gtk_binding_set_activate      (GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers,
+                                              GObject             *object);
+
+GDK_AVAILABLE_IN_ALL
+void           gtk_binding_entry_skip        (GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers);
+GDK_AVAILABLE_IN_ALL
+void           gtk_binding_entry_add_signal  (GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers,
+                                              const gchar         *signal_name,
+                                              guint                n_args,
+                                              ...);
+
+GDK_AVAILABLE_IN_ALL
+GTokenType     gtk_binding_entry_add_signal_from_string
+                                             (GtkBindingSet       *binding_set,
+                                              const gchar         *signal_desc);
+GDK_AVAILABLE_IN_ALL
+void           gtk_binding_entry_add_action_variant
+                                             (GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers,
+                                              const char          *action_name,
+                                              GVariant            *args);
+GDK_AVAILABLE_IN_ALL
+void           gtk_binding_entry_add_action  (GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers,
+                                              const char          *action_name,
+                                              const char          *format_string,
+                                              ...);
+
+GDK_AVAILABLE_IN_ALL
+void           gtk_binding_entry_add_callback(GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers,
+                                              GtkBindingCallback   callback,
+                                              GVariant            *args,
+                                              gpointer             user_data,
+                                              GDestroyNotify       user_destroy);
+
+GDK_AVAILABLE_IN_ALL
+void           gtk_binding_entry_remove      (GtkBindingSet       *binding_set,
+                                              guint                keyval,
+                                              GdkModifierType      modifiers);
+
+G_END_DECLS
+
+#endif /* __GTK_BINDINGS_H__ */
diff --git a/gtk/gtkbindingsprivate.h b/gtk/gtkbindingsprivate.h
new file mode 100644 (file)
index 0000000..b991261
--- /dev/null
@@ -0,0 +1,30 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_BINDINGS_PRIVATE_H__
+#define __GTK_BINDINGS_PRIVATE_H__
+
+#include "gtkbindings.h"
+
+G_BEGIN_DECLS
+
+guint _gtk_binding_parse_binding     (GScanner        *scanner);
+void  _gtk_binding_reset_parsed      (void);
+
+G_END_DECLS
+
+#endif /* __GTK_BINDINGS_PRIVATE_H__ */
index a101faab5c7aff752122de000b57982216ce7294..ba3f367ddc52072bf84b87f64dda4bb9d969c935 100644 (file)
 
 #include "gtkbuilderprivate.h"
 
-#include "gdkpixbufutilsprivate.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderscopeprivate.h"
 #include "gtkdebug.h"
 #include "gtkmain.h"
-#include "gtkicontheme.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
-#include "gtkshortcutactionprivate.h"
-#include "gtkshortcuttrigger.h"
-#include "gtktestutils.h"
 #include "gtktypebuiltins.h"
 #include "gtkicontheme.h"
 #include "gtkiconthemeprivate.h"
+#include "gdkpixbufutilsprivate.h"
 
 static void gtk_builder_finalize       (GObject         *object);
 static void gtk_builder_set_property   (GObject         *object,
@@ -2096,29 +2092,6 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
               ret = FALSE;
             }
         }
-      else if (G_VALUE_HOLDS (value, GTK_TYPE_SHORTCUT_TRIGGER))
-        {
-          GtkShortcutTrigger *trigger = gtk_shortcut_trigger_parse_string (string);
-
-          if (trigger)
-            g_value_take_boxed (value, trigger);
-          else
-            {
-              g_set_error (error,
-                           GTK_BUILDER_ERROR,
-                           GTK_BUILDER_ERROR_INVALID_VALUE,
-                           "Could not parse shortcut trigger '%s'",
-                           string);
-              ret = FALSE;
-            }
-        }
-      else if (G_VALUE_HOLDS (value, GTK_TYPE_SHORTCUT_ACTION))
-        {
-          GtkShortcutAction *action = gtk_shortcut_action_parse_builder (builder, string, error);
-
-          /* Works for success and failure (NULL) case */
-          g_value_take_boxed (value, action);
-        }
       else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
         {
           gchar **vector = g_strsplit (string, "\n", 0);
index 9fb73fa027cbfd7f4c69f8724e56f8eb4bf91bfe..6f3ac11b6d6953244a2e7bfd40b9acd4b0fd076c 100644 (file)
@@ -189,44 +189,35 @@ dismiss_current_popup (GtkColorEditor *editor)
 }
 
 static void
-popup_edit (GtkWidget  *widget,
-            const char *action_name,
-            GVariant   *parameters)
+popup_edit (GtkWidget      *widget,
+            GtkColorEditor *editor)
 {
-  GtkColorEditor *editor = GTK_COLOR_EDITOR (widget);
   GtkWidget *popup = NULL;
   GtkRoot *root;
   GtkWidget *focus;
   gint position;
   gint s, e;
-  const char *param;
-
-  param = g_variant_get_string (parameters, NULL);
 
-  if (strcmp (param, "sv") == 0)
+  if (widget == editor->priv->sv_plane)
     {
       popup = editor->priv->sv_popup;
       focus = editor->priv->s_entry;
       position = 0;
     }
-  else if (strcmp (param, "h") == 0)
+  else if (widget == editor->priv->h_slider)
     {
       popup = editor->priv->h_popup;
       focus = editor->priv->h_entry;
       gtk_range_get_slider_range (GTK_RANGE (editor->priv->h_slider), &s, &e);
       position = (s + e) / 2;
     }
-  else if (strcmp (param, "a") == 0)
+  else if (widget == editor->priv->a_slider)
     {
       popup = editor->priv->a_popup;
       focus = editor->priv->a_entry;
       gtk_range_get_slider_range (GTK_RANGE (editor->priv->a_slider), &s, &e);
       position = (s + e) / 2;
     }
-  else
-    {
-      g_warning ("unsupported popup_edit parameter %s", param);
-    }
 
   if (popup == editor->priv->current_popup)
     dismiss_current_popup (editor);
@@ -553,12 +544,8 @@ gtk_color_editor_class_init (GtkColorEditorClass *class)
   gtk_widget_class_bind_template_callback (widget_class, entry_text_changed);
   gtk_widget_class_bind_template_callback (widget_class, entry_apply);
   gtk_widget_class_bind_template_callback (widget_class, entry_focus_changed);
+  gtk_widget_class_bind_template_callback (widget_class, popup_edit);
   gtk_widget_class_bind_template_callback (widget_class, pick_color);
-
-  gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
-  gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
-  gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
-
 }
 
 static void
index 36a9ca6b8efd428aa5821adffe9d41384a671695..c73b9eec22829eec5bbf63a72f22ebcb7324033e 100644 (file)
 #include "gtksnapshot.h"
 #include "gtkprivate.h"
 #include "gtkeventcontrollerkey.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
 
 struct _GtkColorPlanePrivate
 {
@@ -248,11 +244,11 @@ static void
 hold_action (GtkGestureLongPress *gesture,
              gdouble              x,
              gdouble              y,
-             GtkWidget           *plane)
+             GtkColorPlane       *plane)
 {
-  gtk_widget_activate_action (plane,
-                              "color.edit",
-                              "s", gtk_widget_get_name (plane));
+  gboolean handled;
+
+  g_signal_emit_by_name (plane, "popup-menu", &handled);
 }
 
 static void
@@ -348,7 +344,7 @@ static void
 plane_drag_gesture_begin (GtkGestureDrag *gesture,
                           gdouble         start_x,
                           gdouble         start_y,
-                          GtkWidget      *plane)
+                          GtkColorPlane  *plane)
 {
   guint button;
 
@@ -356,9 +352,9 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
 
   if (button == GDK_BUTTON_SECONDARY)
     {
-      gtk_widget_activate_action (plane,
-                                  "color.edit",
-                                  "s", gtk_widget_get_name (plane));
+      gboolean handled;
+
+      g_signal_emit_by_name (plane, "popup-menu", &handled);
     }
 
   if (button != GDK_BUTTON_PRIMARY)
@@ -367,9 +363,9 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
       return;
     }
 
-  set_cross_cursor (plane, TRUE);
-  update_color (GTK_COLOR_PLANE (plane), start_x, start_y);
-  gtk_widget_grab_focus (plane);
+  set_cross_cursor (GTK_WIDGET (plane), TRUE);
+  update_color (plane, start_x, start_y);
+  gtk_widget_grab_focus (GTK_WIDGET (plane));
   gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
 }
 
@@ -401,9 +397,6 @@ gtk_color_plane_init (GtkColorPlane *plane)
   GtkEventController *controller;
   GtkGesture *gesture;
   AtkObject *atk_obj;
-  GtkShortcutTrigger *trigger;
-  GtkShortcutAction *action;
-  GtkShortcut *shortcut;
 
   plane->priv = gtk_color_plane_get_instance_private (plane);
 
@@ -437,14 +430,6 @@ gtk_color_plane_init (GtkColorPlane *plane)
   g_signal_connect (controller, "key-pressed",
                     G_CALLBACK (key_controller_key_pressed), plane);
   gtk_widget_add_controller (GTK_WIDGET (plane), controller);
-
-  controller = gtk_shortcut_controller_new ();
-  trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
-                                         gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
-  action = gtk_action_action_new ("color.edit");
-  shortcut = gtk_shortcut_new_with_arguments (trigger, action, "s", "sv");
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  gtk_widget_add_controller (GTK_WIDGET (plane), controller);
 }
 
 static void
index 56d120b1114b6270d4dd629c869e9ed6ae19cfd6..d4bc48452ab6218f28f2f8d104480ce81d22fbd1 100644 (file)
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtksnapshot.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
 
 #include <math.h>
 
@@ -52,7 +48,7 @@ enum
 static void hold_action (GtkGestureLongPress *gesture,
                          gdouble              x,
                          gdouble              y,
-                         GtkWidget           *scale);
+                         GtkColorScale       *scale);
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkColorScale, gtk_color_scale, GTK_TYPE_SCALE)
 
@@ -164,29 +160,6 @@ gtk_color_scale_init (GtkColorScale *scale)
   gtk_widget_add_css_class (GTK_WIDGET (scale), "color");
 }
 
-static void
-scale_constructed (GObject *object)
-{
-  GtkColorScale *scale = GTK_COLOR_SCALE (object);
-  GtkColorScalePrivate *priv = gtk_color_scale_get_instance_private (scale);
-  GtkEventController *controller;
-  GtkShortcutTrigger *trigger;
-  GtkShortcutAction *action;
-  GtkShortcut *shortcut;
-
-  controller = gtk_shortcut_controller_new ();
-  trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
-                                         gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
-  action = gtk_action_action_new ("color.edit");
-  shortcut = gtk_shortcut_new_with_arguments (trigger,
-                                              action,
-                                              "s",
-                                              priv->type == GTK_COLOR_SCALE_ALPHA
-                                                ? "a" : "h");
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  gtk_widget_add_controller (GTK_WIDGET (scale), controller);
-}
-
 static void
 scale_get_property (GObject    *object,
                     guint       prop_id,
@@ -250,11 +223,11 @@ static void
 hold_action (GtkGestureLongPress *gesture,
              gdouble              x,
              gdouble              y,
-             GtkWidget           *scale)
+             GtkColorScale       *scale)
 {
-  gtk_widget_activate_action (scale,
-                              "color.edit",
-                              "s", gtk_widget_get_name (scale));
+  gboolean handled;
+
+  g_signal_emit_by_name (scale, "popup-menu", &handled);
 }
 
 static void
@@ -272,7 +245,6 @@ gtk_color_scale_class_init (GtkColorScaleClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
-  object_class->constructed = scale_constructed;
   object_class->finalize = scale_finalize;
   object_class->get_property = scale_get_property;
   object_class->set_property = scale_set_property;
@@ -281,7 +253,6 @@ gtk_color_scale_class_init (GtkColorScaleClass *class)
       g_param_spec_int ("scale-type", P_("Scale type"), P_("Scale type"),
                         0, 1, 0,
                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
 }
 
 void
index f68003cc6936e623caebe322c2e5c70c1f3f516a..ca6ab4d54ff6a7a1c0d956a748a727f559f07c8d 100644 (file)
@@ -348,12 +348,13 @@ gtk_color_swatch_measure (GtkWidget *widget,
   *natural = MAX (*natural, min);
 }
 
-static void
-swatch_popup_menu (GtkWidget  *widget,
-                   const char *action_name,
-                   GVariant   *parameters)
+
+
+static gboolean
+swatch_popup_menu (GtkWidget *widget)
 {
   do_popup (GTK_COLOR_SWATCH (widget));
+  return TRUE;
 }
 
 static void
@@ -479,6 +480,7 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
 
   widget_class->measure = gtk_color_swatch_measure;
   widget_class->snapshot = swatch_snapshot;
+  widget_class->popup_menu = swatch_popup_menu;
   widget_class->size_allocate = swatch_size_allocate;
   widget_class->state_flags_changed = swatch_state_flags_changed;
 
@@ -495,17 +497,6 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
       g_param_spec_boolean ("can-drop", P_("Can Drop"), P_("Whether the swatch should accept drops"),
                             FALSE, GTK_PARAM_READWRITE));
 
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, swatch_popup_menu);
-
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
-
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_COLOR_SWATCH_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("colorswatch"));
 }
index cdf69804e9663238a1e99f91ae2622dfcbb6ca5e..5e5bdd1c3924046296f566d2e8c2a25c5368a3df 100644 (file)
 
 #include "gtkcomboboxprivate.h"
 
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkcellareabox.h"
 #include "gtkcelllayout.h"
 #include "gtkcellrenderertext.h"
 #include "gtkcellview.h"
-#include "gtkeventcontrollerkey.h"
 #include "gtkeventcontrollerscroll.h"
 #include "gtkframe.h"
 #include "gtkbuiltiniconprivate.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
-#include "gtkshortcutcontroller.h"
 #include "gtktogglebutton.h"
 #include "gtktreepopoverprivate.h"
 #include "gtktypebuiltins.h"
-#include "gtkwidgetprivate.h"
+#include "gtkeventcontrollerkey.h"
 
 #include "a11y/gtkcomboboxaccessible.h"
 
@@ -410,6 +409,7 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
   GObjectClass *object_class;
   GtkContainerClass *container_class;
   GtkWidgetClass *widget_class;
+  GtkBindingSet *binding_set;
 
   container_class = (GtkContainerClass *)klass;
   container_class->forall = gtk_combo_box_forall;
@@ -560,77 +560,57 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
                   G_TYPE_STRING, 1, G_TYPE_STRING);
 
   /* key bindings */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Down, GDK_MOD1_MASK,
-                                       "popup",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Down, GDK_MOD1_MASK,
-                                       "popup",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Up, GDK_MOD1_MASK,
-                                       "popdown",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Up, GDK_MOD1_MASK,
-                                       "popdown",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Escape, 0,
-                                       "popdown",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Up, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_STEP_UP);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Up, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_STEP_UP);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Up, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_PAGE_UP);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Page_Up, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_PAGE_UP);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Home, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_START);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_KP_Home, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_START);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Down, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_STEP_DOWN);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Down, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_STEP_DOWN);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Down, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_PAGE_DOWN);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Page_Down, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_PAGE_DOWN);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_End, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_END);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_End, 0,
-                                       "move-active",
-                                       "(i)", GTK_SCROLL_END);
+  binding_set = gtk_binding_set_by_class (widget_class);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Down, GDK_MOD1_MASK,
+                                "popup", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Down, GDK_MOD1_MASK,
+                                "popup", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Up, GDK_MOD1_MASK,
+                                "popdown", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Up, GDK_MOD1_MASK,
+                                "popdown", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
+                                "popdown", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Up, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_UP);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Up, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_UP);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Page_Up, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_UP);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Page_Up, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_UP);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Home, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_START);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Home, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_START);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Down, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_DOWN);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Down, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_DOWN);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Page_Down, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_DOWN);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Page_Down, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_DOWN);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_End, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_END);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_End, 0,
+                                "move-active", 1,
+                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_END);
 
   /* properties */
   g_object_class_override_property (object_class,
@@ -846,7 +826,6 @@ gtk_combo_box_init (GtkComboBox *combo_box)
 {
   GtkComboBoxPrivate *priv = gtk_combo_box_get_instance_private (combo_box);
   GtkEventController *controller;
-  GList *controllers, *list;
 
   priv->active = -1;
   priv->active_row = NULL;
@@ -881,19 +860,6 @@ gtk_combo_box_init (GtkComboBox *combo_box)
                     G_CALLBACK (gtk_combo_box_scroll_controller_scroll),
                     combo_box);
   gtk_widget_add_controller (GTK_WIDGET (combo_box), controller);
-
-  controllers = gtk_widget_list_controllers (priv->popup_widget, GTK_PHASE_BUBBLE);
-  for (list = controllers; list; list = list->next)
-    {
-      if (GTK_IS_SHORTCUT_CONTROLLER (list->data))
-        {
-          g_object_ref (list->data);
-          gtk_widget_remove_controller (priv->popup_widget, list->data);
-          gtk_widget_add_controller (priv->popup_widget, list->data);
-          break;
-        }
-    }
-  g_list_free (controllers);
 }
 
 static void
@@ -1823,7 +1789,18 @@ gtk_combo_box_menu_key (GtkEventControllerKey *key,
                         GdkModifierType        modifiers,
                         GtkComboBox           *combo_box)
 {
-  gtk_event_controller_key_forward (key, GTK_WIDGET (combo_box));
+  GtkWidget *widget;
+  GdkEvent *event;
+
+  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (key));
+  event = gtk_get_current_event ();
+
+  if (!gtk_bindings_activate_event (G_OBJECT (widget), event))
+    {
+      gtk_event_controller_key_forward (key, GTK_WIDGET (combo_box));
+    }
+
+  gdk_event_unref (event);
 
   return TRUE;
 }
diff --git a/gtk/gtkconcatmodel.c b/gtk/gtkconcatmodel.c
deleted file mode 100644 (file)
index d96290e..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/*
- * SECTION:gtkconcatmodel
- * @Short_description: concatenation list model
- * @Title: GtkConcatModel
- * @See_also: #GListModel
- *
- * #GtkConcatModel is a #GListModel implementation that takes a list of list models
- * and presents them as one concatenated list.
- *
- * Node that all the types of the passed in list models must match the concat model's
- * type. If they are not, you must use a common ancestor type for the #GtkConcatModel,
- * %G_TYPE_OBJECT being the ultimate option.
- **/
-
-#include "config.h"
-
-#include "gtkconcatmodelprivate.h"
-
-struct _GtkConcatModel
-{
-  GObject parent_instance;
-
-  GType item_type;
-  guint n_items;
-
-  GList *models;
-};
-
-struct _GtkConcatModelClass
-{
-  GObjectClass parent_class;
-};
-
-static GType
-gtk_concat_model_list_model_get_item_type (GListModel *list)
-{
-  GtkConcatModel *self = GTK_CONCAT_MODEL (list);
-
-  return self->item_type;
-}
-
-static guint
-gtk_concat_model_list_model_get_n_items (GListModel *list)
-{
-  GtkConcatModel *self = GTK_CONCAT_MODEL (list);
-
-  return self->n_items;
-}
-
-static gpointer
-gtk_concat_model_list_model_get_item (GListModel *list,
-                                      guint       position)
-{
-  GtkConcatModel *self = GTK_CONCAT_MODEL (list);
-  GList *l;
-
-  /* FIXME: Use an RBTree to make this O(log N) */
-  for (l = self->models; l; l = l->next)
-    {
-      guint n = g_list_model_get_n_items (l->data);
-
-      if (position < n)
-        return g_list_model_get_item (l->data, position);
-
-      position -= n;
-    }
-
-  return NULL;
-}
-
-static void
-gtk_concat_model_list_model_init (GListModelInterface *iface)
-{
-  iface->get_item_type = gtk_concat_model_list_model_get_item_type;
-  iface->get_n_items = gtk_concat_model_list_model_get_n_items;
-  iface->get_item = gtk_concat_model_list_model_get_item;
-}
-
-G_DEFINE_TYPE_WITH_CODE (GtkConcatModel, gtk_concat_model,
-                         G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_concat_model_list_model_init))
-
-static void
-gtk_concat_model_items_changed (GListModel     *model,
-                                guint           position,
-                                guint           removed,
-                                guint           added,
-                                GtkConcatModel *self)
-{
-  GList *l;
-
-  for (l = self->models; l; l = l->next)
-    {
-      if (l->data == model)
-        break;
-
-      position += g_list_model_get_n_items (l->data);
-    }
-
-  self->n_items -= removed;
-  self->n_items += added;
-
-  g_list_model_items_changed (G_LIST_MODEL (self),
-                              position,
-                              removed,
-                              added);
-}
-
-static void
-gtk_concat_model_remove_internal (GtkConcatModel *self,
-                                  GListModel     *model,
-                                  gboolean        emit_signals)
-{
-  guint n_items, position;
-  GList *l;
-
-  position = 0;
-  for (l = self->models; l; l = l->next)
-    {
-      if (l->data == model)
-        break;
-
-      position += g_list_model_get_n_items (l->data);
-    }
-
-  g_return_if_fail (l != NULL);
-
-  self->models = g_list_delete_link (self->models, l);
-  n_items = g_list_model_get_n_items (model);
-  self->n_items -= n_items;
-  g_signal_handlers_disconnect_by_func (model, gtk_concat_model_items_changed, self);
-  g_object_unref (model);
-  
-  if (n_items && emit_signals)
-    g_list_model_items_changed (G_LIST_MODEL (self),
-                                position,
-                                n_items,
-                                0);
-}
-
-static void
-gtk_concat_model_dispose (GObject *object)
-{
-  GtkConcatModel *self = GTK_CONCAT_MODEL (object);
-
-  /* FIXME: Make this work without signal emissions */
-  while (self->models)
-    gtk_concat_model_remove_internal (self, self->models->data, FALSE);
-
-  G_OBJECT_CLASS (gtk_concat_model_parent_class)->dispose (object);
-}
-
-static void
-gtk_concat_model_class_init (GtkConcatModelClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->dispose = gtk_concat_model_dispose;
-}
-
-static void
-gtk_concat_model_init (GtkConcatModel *self)
-{
-}
-
-GtkConcatModel *
-gtk_concat_model_new (GType item_type)
-{
-  GtkConcatModel *self;
-
-  g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
-
-  self = g_object_new (GTK_TYPE_CONCAT_MODEL, NULL);
-
-  self->item_type = item_type;
-
-  return self;
-}
-
-void
-gtk_concat_model_append (GtkConcatModel *self,
-                         GListModel     *model)
-{
-  guint n_items;
-
-  g_return_if_fail (GTK_IS_CONCAT_MODEL (self));
-  g_return_if_fail (G_IS_LIST_MODEL (model));
-  g_return_if_fail (g_type_is_a (g_list_model_get_item_type (model), self->item_type));
-
-  g_object_ref (model);
-  g_signal_connect (model, "items-changed", G_CALLBACK (gtk_concat_model_items_changed), self);
-  self->models = g_list_append (self->models, model);
-  n_items = g_list_model_get_n_items (model);
-  self->n_items += n_items;
-  
-  if (n_items)
-    g_list_model_items_changed (G_LIST_MODEL (self),
-                                self->n_items - n_items,
-                                0,
-                                n_items);
-}
-
-void
-gtk_concat_model_remove (GtkConcatModel *self,
-                         GListModel     *model)
-{
-  g_return_if_fail (GTK_IS_CONCAT_MODEL (self));
-  g_return_if_fail (G_IS_LIST_MODEL (model));
-
-  gtk_concat_model_remove_internal (self, model, TRUE);
-}
-
-GListModel *
-gtk_concat_model_get_model_for_item (GtkConcatModel *self,
-                                     guint           position)
-{
-  GList *l;
-
-  g_return_val_if_fail (GTK_IS_CONCAT_MODEL (self), NULL);
-
-  /* FIXME: Use an RBTree to make this O(log N) */
-  for (l = self->models; l; l = l->next)
-    {
-      guint n = g_list_model_get_n_items (l->data);
-
-      if (position < n)
-        return l->data;
-
-      position -= n;
-    }
-
-  return NULL;
-}
-
diff --git a/gtk/gtkconcatmodelprivate.h b/gtk/gtkconcatmodelprivate.h
deleted file mode 100644 (file)
index 005a9f3..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_CONCAT_MODEL_H__
-#define __GTK_CONCAT_MODEL_H__
-
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CONCAT_MODEL         (gtk_concat_model_get_type ())
-#define GTK_CONCAT_MODEL(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_CONCAT_MODEL, GtkConcatModel))
-#define GTK_CONCAT_MODEL_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_CONCAT_MODEL, GtkConcatModelClass))
-#define GTK_IS_CONCAT_MODEL(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_CONCAT_MODEL))
-#define GTK_IS_CONCAT_MODEL_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_CONCAT_MODEL))
-#define GTK_CONCAT_MODEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_CONCAT_MODEL, GtkConcatModelClass))
-
-typedef struct _GtkConcatModel GtkConcatModel;
-typedef struct _GtkConcatModelClass GtkConcatModelClass;
-
-GType                   gtk_concat_model_get_type                (void) G_GNUC_CONST;
-
-GtkConcatModel *        gtk_concat_model_new                     (GType                  item_type);
-
-void                    gtk_concat_model_append                  (GtkConcatModel        *self,
-                                                                  GListModel            *model);
-void                    gtk_concat_model_remove                  (GtkConcatModel        *self,
-                                                                  GListModel            *model);
-
-GListModel *            gtk_concat_model_get_model_for_item      (GtkConcatModel        *self,
-                                                                  guint                  position);
-
-G_END_DECLS
-
-#endif /* __GTK_CONCAT_MODEL_H__ */
index a2cc9e15eff9236ea227d51d2cfd652ac2046882..bf9e412cfdb6c4148554ffd9f8f22fffbec3fcbd 100644 (file)
@@ -38,6 +38,7 @@
 #include "gtkcontainerprivate.h"
 #include "gtkmain.h"
 #include "gtkintl.h"
+#include "gtkbindings.h"
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
@@ -489,6 +490,7 @@ gtk_dialog_class_init (GtkDialogClass *class)
   GObjectClass *gobject_class;
   GtkWidgetClass *widget_class;
   GtkWindowClass *window_class;
+  GtkBindingSet *binding_set;
 
   gobject_class = G_OBJECT_CLASS (class);
   widget_class = GTK_WIDGET_CLASS (class);
@@ -563,7 +565,8 @@ gtk_dialog_class_init (GtkDialogClass *class)
                                                      -1, 1, -1,
                                                      GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Escape, 0, "close", NULL);
+  binding_set = gtk_binding_set_by_class (class);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
 
   /* Bind class to template
    */
index 7d31123bf8c24cc442edd96faac02d824e25b409..66594db64584a4381de3e05c1c5efc80f76d5190 100644 (file)
@@ -119,39 +119,12 @@ gtk_emoji_chooser_child_focus (GtkWidget        *widget,
   return GTK_WIDGET_CLASS (gtk_emoji_chooser_child_parent_class)->focus (widget, direction);
 }
 
-static void show_variations (GtkEmojiChooser *chooser,
-                             GtkWidget       *child);
-
-static void
-gtk_emoji_chooser_child_popup_menu (GtkWidget  *widget,
-                                    const char *action_name,
-                                    GVariant   *paramters)
-{
-  GtkWidget *chooser;
-
-  chooser = gtk_widget_get_ancestor (widget, GTK_TYPE_EMOJI_CHOOSER);
-
-  show_variations (GTK_EMOJI_CHOOSER (chooser), widget);
-}
-
 static void
 gtk_emoji_chooser_child_class_init (GtkEmojiChooserChildClass *class)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   widget_class->size_allocate = gtk_emoji_chooser_child_size_allocate;
   widget_class->focus = gtk_emoji_chooser_child_focus;
-
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_emoji_chooser_child_popup_menu);
-
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
-
   gtk_widget_class_set_css_name (widget_class, "emoji");
 }
 
@@ -448,6 +421,16 @@ pressed_cb (GtkGesture *gesture,
   show_variations (chooser, child);
 }
 
+static gboolean
+popup_menu (GtkWidget *widget,
+            gpointer   data)
+{
+  GtkEmojiChooser *chooser = data;
+
+  show_variations (chooser, widget);
+  return TRUE;
+}
+
 static void
 add_emoji (GtkWidget    *box,
            gboolean      prepend,
@@ -505,6 +488,9 @@ add_emoji (GtkWidget    *box,
   if (modifier != 0)
     g_object_set_data (G_OBJECT (child), "modifier", GUINT_TO_POINTER (modifier));
 
+  if (chooser)
+    g_signal_connect (child, "popup-menu", G_CALLBACK (popup_menu), chooser);
+
   gtk_container_add (GTK_CONTAINER (child), label);
   gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
 }
index 13fd885acfa15c33ba0367ee4564f162756092e8..21f7cfe16ebf4b0b97910cbd086f2228dec79603 100644 (file)
@@ -31,6 +31,7 @@
 #include "gtkentryprivate.h"
 
 #include "gtkadjustment.h"
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkbutton.h"
 #include "gtkcelleditable.h"
index 658be5f338b2823b53114534b99130cee4df1a62..8cb42cff20c3b6255deff14c64a3ddafd17ee838 100644 (file)
@@ -972,25 +972,6 @@ typedef enum
   GTK_PAN_DIRECTION_DOWN
 } GtkPanDirection;
 
-/**
- * GtkShortcutScope:
- * @GTK_SHORTCUT_SCOPE_LOCAL: Shortcuts are handled inside
- *     the widget the controller belongs to.
- * @GTK_SHORTCUT_SCOPE_MANAGED: Shortcuts are handled by
- *     the first ancestor that is a #GtkShortcutManager
- * @GTK_SHORTCUT_SCOPE_GLOBAL: Shortcuts are handled by
- *     the root widget.
- *
- * Describes where #GtkShortcuts added to a
- * #GtkShortcutController get handled.
- */
-typedef enum
-{
-  GTK_SHORTCUT_SCOPE_LOCAL,
-  GTK_SHORTCUT_SCOPE_MANAGED,
-  GTK_SHORTCUT_SCOPE_GLOBAL
-} GtkShortcutScope;
-
 /**
  * GtkPopoverConstraint:
  * @GTK_POPOVER_CONSTRAINT_NONE: Don't constrain the popover position
index 500a09b99a0193fccb2c63071f1ec6f60015e9c9..a8a6aaa29649af4631ea45468e676e21b4fa963b 100644 (file)
@@ -35,6 +35,7 @@
 #include "gtkwidgetprivate.h"
 #include "gtkeventcontrollerprivate.h"
 #include "gtkeventcontrollerfocus.h"
+#include "gtkbindings.h"
 #include "gtkenums.h"
 #include "gtkmain.h"
 #include "gtktypebuiltins.h"
index 62614dbf793db45fa6511852385ab1bc1f7e640d..efb1befb58a1098dadc44b3d8b0afc857ebda7bc 100644 (file)
@@ -35,6 +35,7 @@
 #include "gtkwidgetprivate.h"
 #include "gtkeventcontrollerprivate.h"
 #include "gtkeventcontrollerkey.h"
+#include "gtkbindings.h"
 #include "gtkenums.h"
 #include "gtkmain.h"
 #include "gtktypebuiltins.h"
@@ -367,6 +368,9 @@ gtk_event_controller_key_forward (GtkEventControllerKey *controller,
                                   GTK_PHASE_BUBBLE))
     return TRUE;
 
+  if (gtk_bindings_activate_event (G_OBJECT (widget), controller->current_event))
+    return TRUE;
+
   return FALSE;
 }
 
index ec809192e5ccc841fbbad875950833c37b9e87d3..c2c852a1345c099a2e3f3bde2269bccca6f4458b 100644 (file)
@@ -23,6 +23,7 @@
 #include "gtkfilechooserwidgetprivate.h"
 
 #include "gtkbookmarksmanagerprivate.h"
+#include "gtkbindings.h"
 #include "gtkbutton.h"
 #include "gtkcelllayout.h"
 #include "gtkcellrendererpixbuf.h"
 #include "gtkbinlayout.h"
 #include "gtkwidgetprivate.h"
 #include "gtkpopovermenuprivate.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
 
 #include <cairo-gobject.h>
 
@@ -1193,22 +1190,125 @@ places_sidebar_show_error_message_cb (GtkPlacesSidebar *sidebar,
 }
 
 static gboolean
-trigger_location_entry (GtkWidget *widget,
-                        GVariant  *arguments,
-                        gpointer   unused)
+should_trigger_location_entry (GtkFileChooserWidget *impl,
+                               guint                 keyval,
+                               GdkModifierType       state,
+                               const char          **string)
 {
-  GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (widget);
   GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
+  GdkModifierType no_text_input_mask;
 
   if (priv->operation_mode == OPERATION_MODE_SEARCH)
     return FALSE;
 
-  if (priv->action != GTK_FILE_CHOOSER_ACTION_OPEN &&
-      priv->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+  no_text_input_mask =
+    gtk_widget_get_modifier_mask (GTK_WIDGET (impl), GDK_MODIFIER_INTENT_NO_TEXT_INPUT);
+
+  if (state & no_text_input_mask)
     return FALSE;
 
-  location_popup_handler (impl, g_variant_get_string (arguments, NULL));
-  return TRUE;
+  switch (keyval)
+    {
+    case GDK_KEY_slash:
+    case GDK_KEY_KP_Divide:
+      *string = "/";
+      return TRUE;
+
+    case GDK_KEY_period:
+      *string = ".";
+      return TRUE;
+
+    case GDK_KEY_asciitilde:
+      *string = "~";
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
+/* Handles key press events on the file list, so that we can trap Enter to
+ * activate the default button on our own.  Also, checks to see if “/” has been
+ * pressed.
+ */
+static gboolean
+treeview_key_press_cb (GtkEventControllerKey *controller,
+                       guint                  keyval,
+                       guint                  keycode,
+                       GdkModifierType        state,
+                       gpointer               data)
+{
+  GtkFileChooserWidget *impl = (GtkFileChooserWidget *) data;
+  GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
+  const char *string;
+
+  if (should_trigger_location_entry (impl, keyval, state, &string) &&
+      (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+       priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
+    {
+      location_popup_handler (impl, string);
+      return GDK_EVENT_STOP;
+    }
+
+  if ((keyval == GDK_KEY_Return ||
+       keyval == GDK_KEY_ISO_Enter ||
+       keyval == GDK_KEY_KP_Enter ||
+       keyval == GDK_KEY_space ||
+       keyval == GDK_KEY_KP_Space) &&
+      !(state & gtk_accelerator_get_default_mod_mask ()) &&
+      priv->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+    {
+      gtk_widget_activate_default (GTK_WIDGET (impl));
+      return GDK_EVENT_STOP;
+    }
+
+  if (keyval == GDK_KEY_Escape &&
+      priv->operation_mode == OPERATION_MODE_SEARCH)
+    {
+      return gtk_event_controller_key_forward (controller,
+                                               GTK_WIDGET (gtk_search_entry_get_text_widget (GTK_SEARCH_ENTRY (priv->search_entry))));
+    }
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+widget_key_press_cb (GtkEventControllerKey *controller,
+                     guint                  keyval,
+                     guint                  keycode,
+                     GdkModifierType        state,
+                     gpointer               data)
+{
+  GtkFileChooserWidget *impl = (GtkFileChooserWidget *) data;
+  GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
+  gboolean handled = FALSE;
+  const char *string;
+
+  if (should_trigger_location_entry (impl, keyval, state, &string))
+    {
+      if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+          priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+        {
+          location_popup_handler (impl, string);
+          handled = TRUE;
+        }
+    }
+  else
+    {
+      priv->starting_search = TRUE;
+      if (gtk_event_controller_key_forward (controller, priv->search_entry))
+        {
+          gtk_widget_grab_focus (priv->search_entry);
+
+          if (priv->operation_mode != OPERATION_MODE_SEARCH &&
+              priv->starting_search)
+            operation_mode_set (impl, OPERATION_MODE_SEARCH);
+
+          handled = TRUE;
+        }
+    }
+
+  return handled;
 }
 
 /* Callback used from gtk_tree_selection_selected_foreach(); adds a bookmark for
@@ -2032,12 +2132,11 @@ file_list_show_popover (GtkFileChooserWidget *impl,
   gtk_popover_popup (GTK_POPOVER (priv->browse_files_popover));
 }
 
+/* Callback used for the GtkWidget::popup-menu signal of the file list */
 static gboolean
-list_popup_menu_cb (GtkWidget *widget,
-                    GVariant  *args,
-                    gpointer   user_data)
+list_popup_menu_cb (GtkWidget            *widget,
+                    GtkFileChooserWidget *impl)
 {
-  GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
   GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
   graphene_rect_t bounds;
 
@@ -2052,16 +2151,6 @@ list_popup_menu_cb (GtkWidget *widget,
   return FALSE;
 }
 
-static void
-files_list_clicked (GtkGesture           *gesture,
-                    int                   n_press,
-                    double                x,
-                    double                y,
-                    GtkFileChooserWidget *impl)
-{
-  list_popup_menu_cb (NULL, NULL, impl);
-}
-
 /* Callback used when a button is pressed on the file list.  We trap button 3 to
  * bring up a popup menu.
  */
@@ -7372,20 +7461,18 @@ show_hidden_handler (GtkFileChooserWidget *impl)
 }
 
 static void
-add_normal_and_shifted_binding (GtkWidgetClass  *widget_class,
+add_normal_and_shifted_binding (GtkBindingSet   *binding_set,
                                 guint            keyval,
                                 GdkModifierType  modifiers,
                                 const gchar     *signal_name)
 {
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modifiers,
-                                       signal_name,
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set,
+                                keyval, modifiers,
+                                signal_name, 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modifiers | GDK_SHIFT_MASK,
-                                       signal_name,
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set,
+                                keyval, modifiers | GDK_SHIFT_MASK,
+                                signal_name, 0);
 }
 
 static void
@@ -7396,6 +7483,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
   };
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GtkBindingSet *binding_set;
   gint i;
 
   gobject_class->finalize = gtk_file_chooser_widget_finalize;
@@ -7676,84 +7764,71 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
                                 NULL,
                                 G_TYPE_NONE, 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_l, GDK_CONTROL_MASK,
-                                       "location-toggle-popup",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (class);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_v, GDK_CONTROL_MASK,
-                                       "location-popup-on-paste",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_l, GDK_CONTROL_MASK,
+                                "location-toggle-popup",
+                                0);
+
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_v, GDK_CONTROL_MASK,
+                                "location-popup-on-paste",
+                                0);
 
-  add_normal_and_shifted_binding (widget_class,
+  add_normal_and_shifted_binding (binding_set,
                                   GDK_KEY_Up, GDK_MOD1_MASK,
                                   "up-folder");
-  add_normal_and_shifted_binding (widget_class,
+
+  add_normal_and_shifted_binding (binding_set,
                                   GDK_KEY_KP_Up, GDK_MOD1_MASK,
                                   "up-folder");
 
-  add_normal_and_shifted_binding (widget_class,
+  add_normal_and_shifted_binding (binding_set,
                                   GDK_KEY_Down, GDK_MOD1_MASK,
                                   "down-folder");
-  add_normal_and_shifted_binding (widget_class,
+  add_normal_and_shifted_binding (binding_set,
                                   GDK_KEY_KP_Down, GDK_MOD1_MASK,
                                   "down-folder");
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Home, GDK_MOD1_MASK,
-                                       "home-folder",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Home, GDK_MOD1_MASK,
-                                       "home-folder",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_d, GDK_MOD1_MASK,
-                                       "desktop-folder",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_h, GDK_CONTROL_MASK,
-                                       "show-hidden",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_s, GDK_MOD1_MASK,
-                                       "search-shortcut",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_f, GDK_CONTROL_MASK,
-                                       "search-shortcut",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_r, GDK_MOD1_MASK,
-                                       "recent-shortcut",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_p, GDK_MOD1_MASK,
-                                       "places-shortcut",
-                                       NULL);
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_slash, 0,
-                                trigger_location_entry,
-                                "s", "/");
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_KP_Divide, 0,
-                                trigger_location_entry,
-                                "s", "/");
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_period, 0,
-                                trigger_location_entry,
-                                "s", ".");
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_asciitilde, 0,
-                                trigger_location_entry,
-                                "s", "~");
-
-  for (i = 0; i < G_N_ELEMENTS (quick_bookmark_keyvals); i++)
-    gtk_widget_class_add_binding_signal (widget_class,
-                                         quick_bookmark_keyvals[i], GDK_MOD1_MASK,
-                                         "quick-bookmark",
-                                         "(i)", i);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Home, GDK_MOD1_MASK,
+                                "home-folder",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_KP_Home, GDK_MOD1_MASK,
+                                "home-folder",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_d, GDK_MOD1_MASK,
+                                "desktop-folder",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_h, GDK_CONTROL_MASK,
+                                "show-hidden",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_s, GDK_MOD1_MASK,
+                                "search-shortcut",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_f, GDK_CONTROL_MASK,
+                                "search-shortcut",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_r, GDK_MOD1_MASK,
+                                "recent-shortcut",
+                                0);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_p, GDK_MOD1_MASK,
+                                "places-shortcut",
+                                0);
+
+  for (i = 0; i < 10; i++)
+    gtk_binding_entry_add_signal (binding_set,
+                                  quick_bookmark_keyvals[i], GDK_MOD1_MASK,
+                                  "quick-bookmark",
+                                  1, G_TYPE_INT, i);
 
   g_object_class_install_property (gobject_class, PROP_SEARCH_MODE,
                                    g_param_spec_boolean ("search-mode",
@@ -7818,6 +7893,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
   gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, box);
 
   /* And a *lot* of callbacks to bind ... */
+  gtk_widget_class_bind_template_callback (widget_class, list_popup_menu_cb);
   gtk_widget_class_bind_template_callback (widget_class, file_list_query_tooltip_cb);
   gtk_widget_class_bind_template_callback (widget_class, list_row_activated);
   gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
@@ -7837,6 +7913,8 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
   gtk_widget_class_bind_template_callback (widget_class, rename_file_end);
   gtk_widget_class_bind_template_callback (widget_class, click_cb);
   gtk_widget_class_bind_template_callback (widget_class, long_press_cb);
+  gtk_widget_class_bind_template_callback (widget_class, treeview_key_press_cb);
+  gtk_widget_class_bind_template_callback (widget_class, widget_key_press_cb);
 
   gtk_widget_class_set_css_name (widget_class, I_("filechooser"));
 
@@ -7852,11 +7930,6 @@ post_process_ui (GtkFileChooserWidget *impl)
   GList            *cells;
   GFile            *file;
   GtkDropTarget *target;
-  GtkGesture *gesture;
-  GtkEventController *controller;
-  GtkShortcutTrigger *trigger;
-  GtkShortcutAction *action;
-  GtkShortcut *shortcut;
 
   /* Setup file list treeview */
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
@@ -7915,20 +7988,6 @@ post_process_ui (GtkFileChooserWidget *impl)
                                   priv->item_actions);
 
   gtk_search_entry_set_key_capture_widget (GTK_SEARCH_ENTRY (priv->search_entry), priv->search_entry);
-
-  gesture = gtk_gesture_click_new ();
-  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
-  g_signal_connect (gesture, "pressed", G_CALLBACK (files_list_clicked), impl);
-  gtk_widget_add_controller (GTK_WIDGET (priv->browse_files_tree_view), GTK_EVENT_CONTROLLER (gesture));
-
-  controller = gtk_shortcut_controller_new ();
-  trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
-                                         gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
-  action = gtk_callback_action_new (list_popup_menu_cb, impl, NULL);
-  shortcut = gtk_shortcut_new (trigger, action);
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  gtk_widget_add_controller (GTK_WIDGET (priv->browse_files_tree_view), controller);
-
 }
 
 void
index afaa8c38f24f0923b8f365341283db519c25b0c9..1a269e85284d3ade1dad720f871bd5c72e45f9c7 100644 (file)
@@ -78,6 +78,7 @@
 #include "gtkflowbox.h"
 
 #include "gtkadjustment.h"
+#include "gtkbindings.h"
 #include "gtkcontainerprivate.h"
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkcssnodeprivate.h"
@@ -2986,7 +2987,7 @@ gtk_flow_box_focus (GtkWidget        *widget,
 }
 
 static void
-gtk_flow_box_add_move_binding (GtkWidgetClass  *widget_class,
+gtk_flow_box_add_move_binding (GtkBindingSet   *binding_set,
                                guint            keyval,
                                GdkModifierType  modmask,
                                GtkMovementStep  step,
@@ -2997,7 +2998,7 @@ gtk_flow_box_add_move_binding (GtkWidgetClass  *widget_class,
   GdkModifierType modify_mod_mask = GDK_CONTROL_MASK;
 
   display = gdk_display_get_default ();
-  if (display != NULL)
+  if (display)
     {
       extend_mod_mask = gdk_keymap_get_modifier_mask (gdk_display_get_keymap (display),
                                                       GDK_MODIFIER_INTENT_EXTEND_SELECTION);
@@ -3005,22 +3006,26 @@ gtk_flow_box_add_move_binding (GtkWidgetClass  *widget_class,
                                                       GDK_MODIFIER_INTENT_MODIFY_SELECTION);
     }
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | extend_mod_mask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | modify_mod_mask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | extend_mod_mask | modify_mod_mask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | modify_mod_mask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask | modify_mod_mask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
 }
 
 static void
@@ -3382,6 +3387,7 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
   GObjectClass      *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass    *widget_class = GTK_WIDGET_CLASS (class);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GtkBindingSet     *binding_set;
 
   object_class->finalize = gtk_flow_box_finalize;
   object_class->get_property = gtk_flow_box_get_property;
@@ -3658,57 +3664,50 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
 
   widget_class->activate_signal = signals[ACTIVATE_CURSOR_CHILD];
 
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Home, 0,
+  binding_set = gtk_binding_set_by_class (class);
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_End, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Up, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Down, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
 
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Right, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Right, 0,
                                  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
                                  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Left, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Left, 0,
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
-  gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+  gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_space, GDK_CONTROL_MASK,
-                                       "toggle-cursor-child",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, GDK_CONTROL_MASK,
-                                       "toggle-cursor-child",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK,
-                                       "select-all",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "unselect-all",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
+                                "toggle-cursor-child", 0, NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+                                "toggle-cursor-child", 0, NULL);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                                "select-all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "unselect-all", 0);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_FLOW_BOX_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("flowbox"));
index f3bb6ead981245c6d03b01a1cdfd85caa106302f..ab9a9edcedab99fbf23641b6dab3cc93d5734690 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "gtkaccessible.h"
 #include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
 #include "gtkcellareabox.h"
 #include "gtkcellareacontext.h"
 #include "gtkcelllayout.h"
@@ -234,7 +235,7 @@ static gboolean             gtk_icon_view_unselect_all_internal          (GtkIco
 static void                 gtk_icon_view_update_rubberband              (GtkIconView            *icon_view);
 static void                 gtk_icon_view_item_invalidate_size           (GtkIconViewItem        *item);
 static void                 gtk_icon_view_invalidate_sizes               (GtkIconView            *icon_view);
-static void                 gtk_icon_view_add_move_binding               (GtkWidgetClass         *widget_class,
+static void                 gtk_icon_view_add_move_binding               (GtkBindingSet          *binding_set,
                                                                          guint                   keyval,
                                                                          guint                   modmask,
                                                                          GtkMovementStep         step,
@@ -336,9 +337,16 @@ G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER,
 static void
 gtk_icon_view_class_init (GtkIconViewClass *klass)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GObjectClass *gobject_class;
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+  GtkBindingSet *binding_set;
+  
+  binding_set = gtk_binding_set_by_class (klass);
+
+  gobject_class = (GObjectClass *) klass;
+  widget_class = (GtkWidgetClass *) klass;
+  container_class = (GtkContainerClass *) klass;
 
   gobject_class->constructed = gtk_icon_view_constructed;
   gobject_class->dispose = gtk_icon_view_dispose;
@@ -805,88 +813,70 @@ gtk_icon_view_class_init (GtkIconViewClass *klass)
                               _gtk_marshal_BOOLEAN__ENUM_INTv);
 
   /* Key bindings */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK, 
-                                      "select-all",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, 
-                                      "unselect-all",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_space, GDK_CONTROL_MASK, 
-                                      "toggle-cursor-item",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, GDK_CONTROL_MASK,
-                                      "toggle-cursor-item",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_space, 0, 
-                                      "activate-cursor-item",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, 0,
-                                      "activate-cursor-item",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Return, 0, 
-                                      "activate-cursor-item",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_ISO_Enter, 0, 
-                                      "activate-cursor-item",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Enter, 0, 
-                                      "activate-cursor-item",
-                                       NULL);
-
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Up, 0,
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, 
+                               "select-all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, 
+                               "unselect-all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK, 
+                               "toggle-cursor-item", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+                               "toggle-cursor-item", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, 
+                               "activate-cursor-item", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+                               "activate-cursor-item", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, 
+                               "activate-cursor-item", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, 
+                               "activate-cursor-item", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, 
+                               "activate-cursor-item", 0);
+
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Down, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_p, GDK_CONTROL_MASK,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_n, GDK_CONTROL_MASK,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Home, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_End, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Right, 0, 
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Right, 0, 
                                  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Left, 0, 
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Left, 0, 
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Right, 0, 
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Right, 0, 
                                  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
-  gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Left, 0, 
+  gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Left, 0, 
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ICON_VIEW_ACCESSIBLE);
@@ -3415,35 +3405,35 @@ gtk_icon_view_build_items (GtkIconView *icon_view)
 }
 
 static void
-gtk_icon_view_add_move_binding (GtkWidgetClass *widget_class,
+gtk_icon_view_add_move_binding (GtkBindingSet  *binding_set,
                                guint           keyval,
                                guint           modmask,
                                GtkMovementStep step,
                                gint            count)
 {
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                       I_("move-cursor"),
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                                I_("move-cursor"), 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, GDK_SHIFT_MASK,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
+                                "move-cursor", 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
    return;
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "move-cursor", 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
+                                "move-cursor", 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 }
 
 static gboolean
index 49c98a391d634611787ce569a59f68d7e9f93e30..b265373831022af674218e78bebb9149d739646a 100644 (file)
@@ -39,6 +39,7 @@
 #include "gtklabel.h"
 #include "gtkbutton.h"
 #include "gtkenums.h"
+#include "gtkbindings.h"
 #include "gtkdialog.h"
 #include "gtkrevealer.h"
 #include "gtkintl.h"
@@ -377,9 +378,14 @@ gtk_info_bar_dispose (GObject *object)
 static void
 gtk_info_bar_class_init (GtkInfoBarClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+  GtkBindingSet *binding_set;
+
+  object_class = G_OBJECT_CLASS (klass);
+  widget_class = GTK_WIDGET_CLASS (klass);
+  container_class = GTK_CONTAINER_CLASS (klass);
 
   object_class->get_property = gtk_info_bar_get_property;
   object_class->set_property = gtk_info_bar_set_property;
@@ -463,10 +469,9 @@ gtk_info_bar_class_init (GtkInfoBarClass *klass)
                                   NULL,
                                   G_TYPE_NONE, 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Escape, 0,
-                                       "close",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (klass);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
 
   gtk_widget_class_set_css_name (widget_class, I_("infobar"));
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
index b1f12d12e7a78df8a2c8c42c84506ea690192a82..7cd4f4856dccbcdf61aa7638730561ac11a35122 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "gtklabelprivate.h"
 
+#include "gtkbindings.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
 #include "gtkcssnodeprivate.h"
@@ -41,9 +42,6 @@
 #include "gtknotebook.h"
 #include "gtkpango.h"
 #include "gtkprivate.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
 #include "gtkshow.h"
 #include "gtksnapshot.h"
 #include "gtkstylecontextprivate.h"
@@ -278,7 +276,7 @@ struct _GtkLabelPrivate
 {
   GtkLabelSelectionInfo *select_info;
   GtkWidget *mnemonic_widget;
-  GtkEventController *mnemonic_controller;
+  GtkWindow *mnemonic_window;
 
   PangoAttrList *attrs;
   PangoAttrList *markup_attrs;
@@ -416,6 +414,7 @@ static GParamSpec *label_props[NUM_PROPERTIES] = { NULL, };
 static guint signals[LAST_SIGNAL] = { 0 };
 
 static GQuark quark_shortcuts_connected;
+static GQuark quark_mnemonic_menu;
 static GQuark quark_mnemonics_visible_connected;
 static GQuark quark_gtk_signal;
 static GQuark quark_link;
@@ -480,9 +479,7 @@ static void gtk_label_set_markup_internal        (GtkLabel      *label,
 static void gtk_label_recalculate                (GtkLabel      *label);
 static void gtk_label_root                       (GtkWidget     *widget);
 static void gtk_label_unroot                     (GtkWidget     *widget);
-static void gtk_label_popup_menu                 (GtkWidget     *widget,
-                                                  const char    *action_name,
-                                                  GVariant      *parameters);
+static gboolean gtk_label_popup_menu             (GtkWidget     *widget);
 static void gtk_label_do_popup                   (GtkLabel      *label,
                                                   double         x,
                                                   double         y);
@@ -502,7 +499,9 @@ static void gtk_label_update_active_link  (GtkWidget *widget,
 
 static gboolean gtk_label_mnemonic_activate (GtkWidget         *widget,
                                             gboolean           group_cycling);
-static void     gtk_label_setup_mnemonic    (GtkLabel          *label);
+static void     gtk_label_setup_mnemonic    (GtkLabel          *label,
+                                             GtkWidget         *toplevel,
+                                            guint              last_key);
 
 static void     gtk_label_buildable_interface_init   (GtkBuildableIface  *iface);
 static gboolean gtk_label_buildable_custom_tag_start (GtkBuildable       *buildable,
@@ -607,7 +606,7 @@ G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_WIDGET,
                                                 gtk_label_buildable_interface_init))
 
 static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet  *binding_set,
                  guint           keyval,
                  guint           modmask,
                  GtkMovementStep step,
@@ -615,16 +614,18 @@ add_move_binding (GtkWidgetClass *widget_class,
 {
   g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                      "move-cursor",
-                                       "(iib)", step, count, FALSE);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, step,
+                               G_TYPE_INT, count,
+                               G_TYPE_BOOLEAN, FALSE);
 
   /* Selection-extending version */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | GDK_SHIFT_MASK,
-                                      "move-cursor",
-                                       "(iib)", step, count, TRUE);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, step,
+                               G_TYPE_INT, count,
+                               G_TYPE_BOOLEAN, TRUE);
 }
 
 static void
@@ -632,6 +633,7 @@ gtk_label_class_init (GtkLabelClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GtkBindingSet *binding_set;
 
   gobject_class->set_property = gtk_label_set_property;
   gobject_class->get_property = gtk_label_get_property;
@@ -647,6 +649,7 @@ gtk_label_class_init (GtkLabelClass *class)
   widget_class->root = gtk_label_root;
   widget_class->unroot = gtk_label_unroot;
   widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
+  widget_class->popup_menu = gtk_label_popup_menu;
   widget_class->grab_focus = gtk_label_grab_focus;
   widget_class->focus = gtk_label_focus;
   widget_class->get_request_mode = gtk_label_get_request_mode;
@@ -1023,127 +1026,127 @@ gtk_label_class_init (GtkLabelClass *class)
 
   g_object_class_install_properties (gobject_class, NUM_PROPERTIES, label_props);
 
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_label_popup_menu);
-
   /*
    * Key bindings
    */
-
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (class);
 
   /* Moving the insertion point */
-  add_move_binding (widget_class, GDK_KEY_Right, 0,
+  add_move_binding (binding_set, GDK_KEY_Right, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_Left, 0,
+  add_move_binding (binding_set, GDK_KEY_Left, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_f, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_f, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_LOGICAL_POSITIONS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_b, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_b, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_LOGICAL_POSITIONS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, -1);
 
   /* select all */
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_a, GDK_CONTROL_MASK,
-                                (GtkShortcutFunc) gtk_label_select_all,
-                                NULL);
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_slash, GDK_CONTROL_MASK,
-                                (GtkShortcutFunc) gtk_label_select_all,
-                                NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+                               G_TYPE_INT, -1,
+                               G_TYPE_BOOLEAN, FALSE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 1,
+                               G_TYPE_BOOLEAN, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+                               G_TYPE_INT, -1,
+                               G_TYPE_BOOLEAN, FALSE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 1,
+                               G_TYPE_BOOLEAN, TRUE);
 
   /* unselect all */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                      "move-cursor",
-                                       "(iib)", GTK_MOVEMENT_PARAGRAPH_ENDS, 0, FALSE);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_backslash, GDK_CONTROL_MASK,
-                                      "move-cursor",
-                                       "(iib)", GTK_MOVEMENT_PARAGRAPH_ENDS, 0, FALSE);
-
-  add_move_binding (widget_class, GDK_KEY_f, GDK_MOD1_MASK,
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 0,
+                               G_TYPE_BOOLEAN, FALSE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
+                               "move-cursor", 3,
+                               G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 0,
+                               G_TYPE_BOOLEAN, FALSE);
+
+  add_move_binding (binding_set, GDK_KEY_f, GDK_MOD1_MASK,
                    GTK_MOVEMENT_WORDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_b, GDK_MOD1_MASK,
+  add_move_binding (binding_set, GDK_KEY_b, GDK_MOD1_MASK,
                    GTK_MOVEMENT_WORDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_Home, 0,
+  add_move_binding (binding_set, GDK_KEY_Home, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_End, 0,
+  add_move_binding (binding_set, GDK_KEY_End, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_End, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_End, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
 
   /* copy */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_c, GDK_CONTROL_MASK,
-                                      "copy-clipboard",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Return, 0,
-                                      "activate-current-link",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_ISO_Enter, 0,
-                                      "activate-current-link",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Enter, 0,
-                                      "activate-current-link",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
+                               "copy-clipboard", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+                               "activate-current-link", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+                               "activate-current-link", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+                               "activate-current-link", 0);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LABEL_ACCESSIBLE);
 
   gtk_widget_class_set_css_name (widget_class, I_("label"));
 
   quark_shortcuts_connected = g_quark_from_static_string ("gtk-label-shortcuts-connected");
+  quark_mnemonic_menu = g_quark_from_static_string ("gtk-mnemonic-menu");
   quark_mnemonics_visible_connected = g_quark_from_static_string ("gtk-label-mnemonics-visible-connected");
   quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
   quark_link = g_quark_from_static_string ("link");
@@ -1346,6 +1349,7 @@ gtk_label_init (GtkLabel *label)
   priv->attrs = NULL;
 
   priv->mnemonic_widget = NULL;
+  priv->mnemonic_window = NULL;
 
   priv->mnemonics_visible = FALSE;
 }
@@ -1813,41 +1817,30 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
 }
 
 static void
-gtk_label_setup_mnemonic (GtkLabel *label)
+gtk_label_setup_mnemonic (GtkLabel  *label,
+                          GtkWidget *toplevel,
+                         guint      last_key)
 {
   GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
   GtkWidget *widget = GTK_WIDGET (label);
-  GtkShortcut *shortcut;
   
-  if (priv->mnemonic_keyval == GDK_KEY_VoidSymbol)
+  if (last_key != GDK_KEY_VoidSymbol)
     {
-      if (priv->mnemonic_controller)
-        {
-          gtk_widget_remove_controller (widget, priv->mnemonic_controller);
-          priv->mnemonic_controller = NULL;
-        }
-      return;
+      if (priv->mnemonic_window)
+       {
+         gtk_window_remove_mnemonic  (priv->mnemonic_window,
+                                      last_key,
+                                      widget);
+         priv->mnemonic_window = NULL;
+       }
     }
 
-  if (priv->mnemonic_controller == NULL)
-    {
-      priv->mnemonic_controller = gtk_shortcut_controller_new ();
-      gtk_event_controller_set_propagation_phase (priv->mnemonic_controller, GTK_PHASE_CAPTURE);
-      gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (priv->mnemonic_controller), GTK_SHORTCUT_SCOPE_MANAGED);
-      shortcut = gtk_shortcut_new (gtk_mnemonic_trigger_new (priv->mnemonic_keyval),
-                                   gtk_mnemonic_action_new ());
-      gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (priv->mnemonic_controller), shortcut);
-      gtk_widget_add_controller (GTK_WIDGET (label), priv->mnemonic_controller);
-      g_object_unref (shortcut);
-    }
-  else
-    {
-      shortcut = g_list_model_get_item (G_LIST_MODEL (priv->mnemonic_controller), 0);
-      gtk_shortcut_set_trigger (shortcut, gtk_mnemonic_trigger_new (priv->mnemonic_keyval));
-      g_object_unref (shortcut);
-    }
+  if (priv->mnemonic_keyval == GDK_KEY_VoidSymbol)
+      goto done;
 
   connect_mnemonics_visible_notify (GTK_LABEL (widget));
+
+ done:;
 }
 
 static void
@@ -1890,12 +1883,13 @@ static void
 gtk_label_root (GtkWidget *widget)
 {
   GtkLabel *label = GTK_LABEL (widget);
+  GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
   GtkSettings *settings;
   gboolean shortcuts_connected;
 
   GTK_WIDGET_CLASS (gtk_label_parent_class)->root (widget);
 
-  gtk_label_setup_mnemonic (label);
+  gtk_label_setup_mnemonic (label, GTK_WIDGET (gtk_widget_get_root (widget)), priv->mnemonic_keyval);
 
   /* The PangoContext is replaced when the display changes, so clear the layouts */
   gtk_label_clear_layout (GTK_LABEL (widget));
@@ -1922,8 +1916,9 @@ static void
 gtk_label_unroot (GtkWidget *widget)
 {
   GtkLabel *label = GTK_LABEL (widget);
+  GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
 
-  gtk_label_setup_mnemonic (label);
+  gtk_label_setup_mnemonic (label, NULL, priv->mnemonic_keyval);
 
   GTK_WIDGET_CLASS (gtk_label_parent_class)->unroot (widget);
 }
@@ -2171,7 +2166,7 @@ gtk_label_recalculate (GtkLabel *label)
 
   if (keyval != priv->mnemonic_keyval)
     {
-      gtk_label_setup_mnemonic (label);
+      gtk_label_setup_mnemonic (label, GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (label))), keyval);
       g_object_notify_by_pspec (G_OBJECT (label), label_props[PROP_MNEMONIC_KEYVAL]);
     }
 
@@ -6071,14 +6066,13 @@ gtk_label_do_popup (GtkLabel *label,
   gtk_popover_popup (GTK_POPOVER (priv->popup_menu));
 }
 
-static void
-gtk_label_popup_menu (GtkWidget  *widget,
-                      const char *action_name,
-                      GVariant   *parameters)
+static gboolean
+gtk_label_popup_menu (GtkWidget *widget)
 {
   GtkLabel *label = GTK_LABEL (widget);
 
   gtk_label_do_popup (label, -1, -1);
+  return TRUE;
 }
 
 static void
index 96831ec0834a05c1ca2addca3bcbd109887ef1aa..d64c3f3a83bc0cb41a084c597b354e1b40f55167 100644 (file)
@@ -123,9 +123,7 @@ static void     gtk_link_button_set_property (GObject          *object,
                                              const GValue     *value,
                                              GParamSpec       *pspec);
 static void     gtk_link_button_clicked      (GtkButton        *button);
-static void     gtk_link_button_popup_menu   (GtkWidget        *widget,
-                                              const char       *action_name,
-                                              GVariant         *parameters);
+static gboolean gtk_link_button_popup_menu   (GtkWidget        *widget);
 static gboolean gtk_link_button_query_tooltip_cb (GtkWidget    *widget,
                                                   gint          x,
                                                   gint          y,
@@ -171,6 +169,8 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass)
   gobject_class->get_property = gtk_link_button_get_property;
   gobject_class->finalize = gtk_link_button_finalize;
 
+  widget_class->popup_menu = gtk_link_button_popup_menu;
+
   button_class->clicked = gtk_link_button_clicked;
 
   klass->activate_link = gtk_link_button_activate_link;
@@ -230,17 +230,6 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass)
 
   gtk_widget_class_install_action (widget_class, "clipboard.copy", NULL,
                                    gtk_link_button_activate_clipboard_copy);
-
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_link_button_popup_menu);
-
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
 }
 
 static GMenuModel *
@@ -514,12 +503,11 @@ gtk_link_button_clicked (GtkButton *button)
   g_signal_emit (button, link_signals[ACTIVATE_LINK], 0, &retval);
 }
 
-static void
-gtk_link_button_popup_menu (GtkWidget  *widget,
-                            const char *action_name,
-                            GVariant   *parameters)
+static gboolean
+gtk_link_button_popup_menu (GtkWidget *widget)
 {
   gtk_link_button_do_popup (GTK_LINK_BUTTON (widget), -1, -1);
+  return TRUE;
 }
 
 /**
index c5de9395134c89e5f3b5998129f5a26739d267ef..ffa4a0112cb2ee21037589b28304f10a35c58d79 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "gtkactionhelperprivate.h"
 #include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
 #include "gtkbuildable.h"
 #include "gtkcontainerprivate.h"
 #include "gtkcssnodeprivate.h"
@@ -231,7 +232,7 @@ static GSequenceIter *      gtk_list_box_get_next_visible             (GtkListBo
                                                                        GSequenceIter       *iter);
 static void                 gtk_list_box_apply_filter                 (GtkListBox          *box,
                                                                        GtkListBoxRow       *row);
-static void                 gtk_list_box_add_move_binding             (GtkWidgetClass      *widget_class,
+static void                 gtk_list_box_add_move_binding             (GtkBindingSet       *binding_set,
                                                                        guint                keyval,
                                                                        GdkModifierType      modmask,
                                                                        GtkMovementStep      step,
@@ -435,6 +436,9 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkBindingSet *binding_set;
+
+  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LIST_BOX_ACCESSIBLE);
 
   object_class->get_property = gtk_list_box_get_property;
   object_class->set_property = gtk_list_box_set_property;
@@ -607,52 +611,43 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
 
   widget_class->activate_signal = signals[ACTIVATE_CURSOR_ROW];
 
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_Home, 0,
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_End, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_Up, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_Down, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
-  gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+  gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_space, GDK_CONTROL_MASK,
-                                       "toggle-cursor-row",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, GDK_CONTROL_MASK,
-                                       "toggle-cursor-row",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK,
-                                       "select-all",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "unselect-all",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
+                                "toggle-cursor-row", 0, NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+                                "toggle-cursor-row", 0, NULL);
 
-  gtk_widget_class_set_css_name (widget_class, I_("list"));
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                                "select-all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "unselect-all", 0);
 
-  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LIST_BOX_ACCESSIBLE);
+  gtk_widget_class_set_css_name (widget_class, I_("list"));
 }
 
 static void
@@ -1440,7 +1435,7 @@ gtk_list_box_set_accept_unpaired_release (GtkListBox *box,
 }
 
 static void
-gtk_list_box_add_move_binding (GtkWidgetClass  *widget_class,
+gtk_list_box_add_move_binding (GtkBindingSet   *binding_set,
                                guint            keyval,
                                GdkModifierType  modmask,
                                GtkMovementStep  step,
@@ -1459,22 +1454,26 @@ gtk_list_box_add_move_binding (GtkWidgetClass  *widget_class,
                                                       GDK_MODIFIER_INTENT_MODIFY_SELECTION);
     }
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | extend_mod_mask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | modify_mod_mask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | extend_mod_mask | modify_mod_mask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | modify_mod_mask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask | modify_mod_mask,
+                                "move-cursor", 2,
+                                GTK_TYPE_MOVEMENT_STEP, step,
+                                G_TYPE_INT, count,
+                                NULL);
 }
 
 static void
index 9fd83c07dc324db73d4a9ec0db9f8b419ced4d11..bc164008bb4daa33c208a94bf930caac1bbaef2f 100644 (file)
 
 #include "gtkintl.h"
 
+#include "gtkaccelmapprivate.h"
 #include "gtkbox.h"
 #include "gtkdebug.h"
 #include "gtkdropprivate.h"
@@ -662,6 +663,8 @@ do_post_parse_initialization (void)
   gsk_ensure_resources ();
   _gtk_ensure_resources ();
 
+  _gtk_accel_map_init ();
+
   gtk_initialized = TRUE;
 
 #ifdef G_OS_UNIX
@@ -1694,11 +1697,14 @@ gtk_main_do_event (GdkEvent *event)
   current_events = g_list_prepend (current_events, event);
 
   if (is_pointing_event (event))
-    {
-      target_widget = handle_pointing_event (event);
-    }
+    target_widget = handle_pointing_event (event);
   else if (is_key_event (event))
     {
+      if (gdk_event_get_event_type (event) == GDK_KEY_PRESS &&
+          GTK_IS_WINDOW (target_widget) &&
+          gtk_window_activate_key (GTK_WINDOW (target_widget), event))
+        goto cleanup;
+
       target_widget = handle_key_event (event);
     }
   else if (is_focus_event (event))
diff --git a/gtk/gtkmnemonichash.c b/gtk/gtkmnemonichash.c
new file mode 100644 (file)
index 0000000..e650484
--- /dev/null
@@ -0,0 +1,201 @@
+/* gtkmnemonichash.c: Sets of mnemonics with cycling
+ *
+ * GTK - The GIMP Toolkit
+ * Copyright (C) 2002, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkmnemonichash.h"
+#include "gtknative.h"
+
+struct _GtkMnemnonicHash
+{
+  GHashTable *hash;
+};
+
+
+GtkMnemonicHash *
+_gtk_mnemonic_hash_new (void)
+{
+  GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1);
+
+  mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL);
+
+  return mnemonic_hash;
+}
+
+static void
+mnemonic_hash_free_foreach (gpointer   key,
+                           gpointer    value,
+                           gpointer    user)
+{
+  guint keyval = GPOINTER_TO_UINT (key);
+  GSList *targets = value;
+
+  gchar *name = gtk_accelerator_name (keyval, 0);
+      
+  g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
+            name, targets->data);
+  g_free (name);
+  
+  g_slist_free (targets);
+}
+
+void
+_gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash)
+{
+  g_hash_table_foreach (mnemonic_hash->hash,
+                       mnemonic_hash_free_foreach,
+                       NULL);
+
+  g_hash_table_destroy (mnemonic_hash->hash);
+  g_free (mnemonic_hash);
+}
+
+void
+_gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
+                       guint            keyval,
+                       GtkWidget       *target)
+{
+  gpointer key = GUINT_TO_POINTER (keyval);
+  GSList *targets, *new_targets;
+  
+  g_return_if_fail (GTK_IS_WIDGET (target));
+  
+  targets = g_hash_table_lookup (mnemonic_hash->hash, key);
+  g_return_if_fail (g_slist_find (targets, target) == NULL);
+
+  new_targets = g_slist_append (targets, target);
+  if (new_targets != targets)
+    g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
+}
+
+void
+_gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
+                          guint           keyval,
+                          GtkWidget      *target)
+{
+  gpointer key = GUINT_TO_POINTER (keyval);
+  GSList *targets, *new_targets;
+  
+  g_return_if_fail (GTK_IS_WIDGET (target));
+  
+  targets = g_hash_table_lookup (mnemonic_hash->hash, key);
+
+  g_return_if_fail (targets && g_slist_find (targets, target) != NULL);
+
+  new_targets = g_slist_remove (targets, target);
+  if (new_targets != targets)
+    {
+      if (new_targets == NULL)
+       g_hash_table_remove (mnemonic_hash->hash, key);
+      else
+       g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
+    }
+}
+
+gboolean
+_gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
+                            guint            keyval)
+{
+  GSList *list, *targets;
+  GtkWidget *widget, *chosen_widget;
+  GdkSurface *surface;
+  gboolean overloaded;
+
+  targets = g_hash_table_lookup (mnemonic_hash->hash,
+                                GUINT_TO_POINTER (keyval));
+  if (!targets)
+    return FALSE;
+  
+  overloaded = FALSE;
+  chosen_widget = NULL;
+  for (list = targets; list; list = list->next)
+    {
+      widget = GTK_WIDGET (list->data);
+      surface = gtk_native_get_surface (gtk_widget_get_native (widget));
+
+      if (gtk_widget_is_sensitive (widget) &&
+         gtk_widget_get_mapped (widget) &&
+          surface && gdk_surface_is_viewable (surface))
+       {
+         if (chosen_widget)
+           {
+             overloaded = TRUE;
+             break;
+           }
+         else
+           chosen_widget = widget;
+       }
+    }
+
+  if (chosen_widget)
+    {
+      /* For round robin we put the activated entry on
+       * the end of the list after activation
+       */
+      targets = g_slist_remove (targets, chosen_widget);
+      targets = g_slist_append (targets, chosen_widget);
+      g_hash_table_insert (mnemonic_hash->hash,
+                          GUINT_TO_POINTER (keyval),
+                          targets);
+
+      return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
+    }
+  return FALSE;
+}
+
+GSList *
+_gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
+                          guint            keyval)
+{
+  return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval));
+}
+
+static void
+mnemonic_hash_foreach_func (gpointer key,
+                           gpointer value,
+                           gpointer data)
+{
+  struct {
+    GtkMnemonicHashForeach func;
+    gpointer func_data;
+  } *info = data;
+
+  guint keyval = GPOINTER_TO_UINT (key);
+  GSList *targets = value;
+  
+  (*info->func) (keyval, targets, info->func_data);
+}
+
+void
+_gtk_mnemonic_hash_foreach (GtkMnemonicHash       *mnemonic_hash,
+                           GtkMnemonicHashForeach func,
+                           gpointer               func_data)
+{
+  struct {
+    GtkMnemonicHashForeach func;
+    gpointer func_data;
+  } info;
+  
+  info.func = func;
+  info.func_data = func_data;
+
+  g_hash_table_foreach (mnemonic_hash->hash,
+                       mnemonic_hash_foreach_func,
+                       &info);
+}
diff --git a/gtk/gtkmnemonichash.h b/gtk/gtkmnemonichash.h
new file mode 100644 (file)
index 0000000..832b2ee
--- /dev/null
@@ -0,0 +1,52 @@
+/* gtkmnemonichash.h: Sets of mnemonics with cycling
+ *
+ * GTK - The GIMP Toolkit
+ * Copyright (C) 2002, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_MNEMONIC_HASH_H__
+#define __GTK_MNEMONIC_HASH_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkMnemnonicHash GtkMnemonicHash;
+
+typedef void (*GtkMnemonicHashForeach) (guint      keyval,
+                                       GSList    *targets,
+                                       gpointer   data);
+
+GtkMnemonicHash *_gtk_mnemonic_hash_new      (void);
+void             _gtk_mnemonic_hash_free     (GtkMnemonicHash        *mnemonic_hash);
+void             _gtk_mnemonic_hash_add      (GtkMnemonicHash        *mnemonic_hash,
+                                             guint                   keyval,
+                                             GtkWidget              *target);
+void             _gtk_mnemonic_hash_remove   (GtkMnemonicHash        *mnemonic_hash,
+                                             guint                   keyval,
+                                             GtkWidget              *target);
+gboolean         _gtk_mnemonic_hash_activate (GtkMnemonicHash        *mnemonic_hash,
+                                             guint                   keyval);
+GSList *         _gtk_mnemonic_hash_lookup   (GtkMnemonicHash        *mnemonic_hash,
+                                             guint                   keyval);
+void             _gtk_mnemonic_hash_foreach  (GtkMnemonicHash        *mnemonic_hash,
+                                             GtkMnemonicHashForeach  func,
+                                             gpointer                func_data);
+
+G_END_DECLS
+
+#endif /* __GTK_MNEMONIC_HASH_H__ */
index 49b69b28e85edeeca055a00ea4e4429e645c702f..25c75087efb01350149be9a3f6d7c80db74008e6 100644 (file)
@@ -727,6 +727,7 @@ update_accel (GtkModelButton *self,
     {
       guint key;
       GdkModifierType mods;
+      GtkAccelLabelClass *accel_class;
       char *str;
 
       if (!self->accel_label)
@@ -738,9 +739,12 @@ update_accel (GtkModelButton *self,
         }
 
       gtk_accelerator_parse (accel, &key, &mods);
-      str = gtk_accelerator_get_label (key, mods);
+
+      accel_class = g_type_class_ref (GTK_TYPE_ACCEL_LABEL);
+      str = _gtk_accel_label_class_get_accelerator_label (accel_class, key, mods);
       gtk_label_set_label (GTK_LABEL (self->accel_label), str);
       g_free (str);
+      g_type_class_unref (accel_class);
     }
   else
     {
index a3debb086126ae05a7899ab4127bce9fea20274b..51d926c401b50d23d4732bcfc4db2ec12513b666 100644 (file)
 #include "gtkpopover.h"
 #include "gtksnapshot.h"
 #include "gdktextureprivate.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
 #include <glib/gprintf.h>
 
 /**
@@ -1462,7 +1458,6 @@ do_popup_menu_for_process_tree_view (GtkWidget         *widget,
 
 static gboolean
 on_popup_menu_for_process_tree_view (GtkWidget *widget,
-                                     GVariant  *args,
                                      gpointer   user_data)
 {
   GtkMountOperation *op = GTK_MOUNT_OPERATION (user_data);
@@ -1508,10 +1503,6 @@ create_show_processes_dialog (GtkMountOperation *op,
   gchar *s;
   gboolean use_header;
   GtkGesture *gesture;
-  GtkEventController *controller;
-  GtkShortcutTrigger *trigger;
-  GtkShortcutAction *action;
-  GtkShortcut *shortcut;
 
   priv = op->priv;
 
@@ -1598,15 +1589,9 @@ create_show_processes_dialog (GtkMountOperation *op,
   gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
   gtk_container_add (GTK_CONTAINER (vbox), scrolled_window);
 
-  controller = gtk_shortcut_controller_new ();
-  trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
-                                         gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
-  action = gtk_callback_action_new (on_popup_menu_for_process_tree_view,
-                                    op,
-                                    NULL);
-  shortcut = gtk_shortcut_new_with_arguments (trigger, action, "s", "sv");
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  gtk_widget_add_controller (GTK_WIDGET (tree_view), controller);
+  g_signal_connect (tree_view, "popup-menu",
+                    G_CALLBACK (on_popup_menu_for_process_tree_view),
+                    op);
 
   gesture = gtk_gesture_click_new ();
   gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
index a62501310944e33fb2f81996a5eb85694a68d735..d20342b1f2605e54303be6dfbb943b7257e9f8e8 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "gtknotebook.h"
 
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkboxlayout.h"
 #include "gtkbuildable.h"
@@ -772,9 +773,7 @@ static void gtk_notebook_dispose             (GObject         *object);
 /*** GtkWidget Methods ***/
 static void gtk_notebook_destroy             (GtkWidget        *widget);
 static void gtk_notebook_unmap               (GtkWidget        *widget);
-static void gtk_notebook_popup_menu          (GtkWidget        *widget,
-                                              const char       *action_name,
-                                              GVariant         *parameters);
+static gboolean gtk_notebook_popup_menu      (GtkWidget        *widget);
 static void gtk_notebook_motion              (GtkEventController *controller,
                                               double              x,
                                               double              y,
@@ -936,53 +935,49 @@ G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
                                                 gtk_notebook_buildable_init))
 
 static void
-add_tab_bindings (GtkWidgetClass   *widget_class,
+add_tab_bindings (GtkBindingSet    *binding_set,
                   GdkModifierType   modifiers,
                   GtkDirectionType  direction)
 {
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Tab, modifiers,
-                                       "move_focus_out",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Tab, modifiers,
-                                       "move_focus_out",
-                                       "(i)", direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+                                "move_focus_out", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+                                "move_focus_out", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
-add_arrow_bindings (GtkWidgetClass   *widget_class,
+add_arrow_bindings (GtkBindingSet    *binding_set,
                     guint             keysym,
                     GtkDirectionType  direction)
 {
   guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keysym, GDK_CONTROL_MASK,
-                                       "move_focus_out",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keypad_keysym, GDK_CONTROL_MASK,
-                                       "move_focus_out",
-                                       "(i)", direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                "move_focus_out", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+                                "move_focus_out", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
-add_reorder_bindings (GtkWidgetClass   *widget_class,
+add_reorder_bindings (GtkBindingSet    *binding_set,
                       guint             keysym,
                       GtkDirectionType  direction,
                       gboolean          move_to_last)
 {
   guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keysym, GDK_MOD1_MASK,
-                                       "reorder_tab",
-                                       "(ib)", direction, move_to_last);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keypad_keysym, GDK_MOD1_MASK,
-                                       "reorder_tab",
-                                       "(ib)", direction, move_to_last);
+  gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
+                                "reorder_tab", 2,
+                                GTK_TYPE_DIRECTION_TYPE, direction,
+                                G_TYPE_BOOLEAN, move_to_last);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
+                                "reorder_tab", 2,
+                                GTK_TYPE_DIRECTION_TYPE, direction,
+                                G_TYPE_BOOLEAN, move_to_last);
 }
 
 static gboolean
@@ -1040,6 +1035,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
   GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GtkBindingSet *binding_set;
 
   gobject_class->set_property = gtk_notebook_set_property;
   gobject_class->get_property = gtk_notebook_get_property;
@@ -1048,6 +1044,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
 
   widget_class->destroy = gtk_notebook_destroy;
   widget_class->unmap = gtk_notebook_unmap;
+  widget_class->popup_menu = gtk_notebook_popup_menu;
   widget_class->grab_notify = gtk_notebook_grab_notify;
   widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
   widget_class->direction_changed = gtk_notebook_direction_changed;
@@ -1311,77 +1308,67 @@ gtk_notebook_class_init (GtkNotebookClass *class)
                               G_TYPE_FROM_CLASS (gobject_class),
                               _gtk_marshal_OBJECT__OBJECTv);
 
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_notebook_popup_menu);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_space, 0,
-                                       "select-page",
-                                       "(b)", FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, 0,
-                                       "select-page",
-                                       "(b)", FALSE);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Home, 0,
-                                       "focus-tab",
-                                       "(i)", GTK_NOTEBOOK_TAB_FIRST);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Home, 0,
-                                       "focus-tab",
-                                       "(i)", GTK_NOTEBOOK_TAB_FIRST);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_End, 0,
-                                       "focus-tab",
-                                       "(i)", GTK_NOTEBOOK_TAB_LAST);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_End, 0,
-                                       "focus-tab",
-                                       "(i)", GTK_NOTEBOOK_TAB_LAST);
-
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Up, GDK_CONTROL_MASK,
-                                       "change-current-page",
-                                       "(i)", -1);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Down, GDK_CONTROL_MASK,
-                                       "change-current-page",
-                                       "(i)", 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
-                                       "change-current-page",
-                                       "(i)", -1);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
-                                       "change-current-page",
-                                       "(i)", 1);
-
-  add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
-  add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
-  add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
-  add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
-  add_reorder_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP, FALSE);
-  add_reorder_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN, FALSE);
-  add_reorder_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT, FALSE);
-  add_reorder_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT, FALSE);
-  add_reorder_bindings (widget_class, GDK_KEY_Home, GTK_DIR_LEFT, TRUE);
-  add_reorder_bindings (widget_class, GDK_KEY_Home, GTK_DIR_UP, TRUE);
-  add_reorder_bindings (widget_class, GDK_KEY_End, GTK_DIR_RIGHT, TRUE);
-  add_reorder_bindings (widget_class, GDK_KEY_End, GTK_DIR_DOWN, TRUE);
-
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+  binding_set = gtk_binding_set_by_class (class);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_space, 0,
+                                "select-page", 1,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_KP_Space, 0,
+                                "select-page", 1,
+                                G_TYPE_BOOLEAN, FALSE);
+
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Home, 0,
+                                "focus-tab", 1,
+                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_KP_Home, 0,
+                                "focus-tab", 1,
+                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_End, 0,
+                                "focus-tab", 1,
+                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_KP_End, 0,
+                                "focus-tab", 1,
+                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
+
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Up, GDK_CONTROL_MASK,
+                                "change-current-page", 1,
+                                G_TYPE_INT, -1);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Down, GDK_CONTROL_MASK,
+                                "change-current-page", 1,
+                                G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
+                                "change-current-page", 1,
+                                G_TYPE_INT, -1);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
+                                "change-current-page", 1,
+                                G_TYPE_INT, 1);
+
+  add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+  add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+  add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+  add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+  add_reorder_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP, FALSE);
+  add_reorder_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN, FALSE);
+  add_reorder_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT, FALSE);
+  add_reorder_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT, FALSE);
+  add_reorder_bindings (binding_set, GDK_KEY_Home, GTK_DIR_LEFT, TRUE);
+  add_reorder_bindings (binding_set, GDK_KEY_Home, GTK_DIR_UP, TRUE);
+  add_reorder_bindings (binding_set, GDK_KEY_End, GTK_DIR_RIGHT, TRUE);
+  add_reorder_bindings (binding_set, GDK_KEY_End, GTK_DIR_DOWN, TRUE);
+
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_NOTEBOOK_ACCESSIBLE);
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
@@ -2611,16 +2598,20 @@ gtk_notebook_gesture_pressed (GtkGestureClick *gesture,
     }
 }
 
-static void
-gtk_notebook_popup_menu (GtkWidget  *widget,
-                         const char *action_name,
-                         GVariant   *parameters)
+
+static gboolean
+gtk_notebook_popup_menu (GtkWidget *widget)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
   GtkNotebookPrivate *priv = notebook->priv;
 
   if (priv->menu)
-    gtk_popover_popup (GTK_POPOVER (priv->menu));
+    {
+      gtk_popover_popup (GTK_POPOVER (priv->menu));
+      return TRUE;
+    }
+
+  return FALSE;
 }
 
 static void
index 96c937ca133e38b308b467da54d529657535f84f..b3969579061528a15a2e62e6cfd5da5d8d3cc1b2 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "gtkpaned.h"
 
+#include "gtkbindings.h"
 #include "gtkcontainerprivate.h"
 #include "gtkcssnodeprivate.h"
 #include "gtkcssstylepropertyprivate.h"
@@ -277,29 +278,24 @@ static guint signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *paned_props[LAST_PROP] = { NULL, };
 
 static void
-add_tab_bindings (GtkWidgetClass  *widget_class,
-                 GdkModifierType  modifiers)
+add_tab_bindings (GtkBindingSet    *binding_set,
+                 GdkModifierType   modifiers)
 {
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Tab, modifiers,
-                                       "toggle-handle-focus",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Tab, modifiers,
-                                      "toggle-handle-focus",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+                                "toggle-handle-focus", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+                               "toggle-handle-focus", 0);
 }
 
 static void
-add_move_binding (GtkWidgetClass  *widget_class,
+add_move_binding (GtkBindingSet   *binding_set,
                  guint            keyval,
                  GdkModifierType  mask,
                  GtkScrollType    scroll)
 {
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, mask,
-                                      "move-handle",
-                                       "(i)", scroll);
+  gtk_binding_entry_add_signal (binding_set, keyval, mask,
+                               "move-handle", 1,
+                               GTK_TYPE_SCROLL_TYPE, scroll);
 }
 
 static void
@@ -341,9 +337,16 @@ gtk_paned_handle_contains (GtkGizmo *handle,
 static void
 gtk_paned_class_init (GtkPanedClass *class)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+  GtkPanedClass *paned_class;
+  GtkBindingSet *binding_set;
+
+  object_class = (GObjectClass *) class;
+  widget_class = (GtkWidgetClass *) class;
+  container_class = (GtkContainerClass *) class;
+  paned_class = (GtkPanedClass *) class;
 
   object_class->set_property = gtk_paned_set_property;
   object_class->get_property = gtk_paned_get_property;
@@ -361,12 +364,12 @@ gtk_paned_class_init (GtkPanedClass *class)
   container_class->child_type = gtk_paned_child_type;
   container_class->set_focus_child = gtk_paned_set_focus_child;
 
-  class->cycle_child_focus = gtk_paned_cycle_child_focus;
-  class->toggle_handle_focus = gtk_paned_toggle_handle_focus;
-  class->move_handle = gtk_paned_move_handle;
-  class->cycle_handle_focus = gtk_paned_cycle_handle_focus;
-  class->accept_position = gtk_paned_accept_position;
-  class->cancel_position = gtk_paned_cancel_position;
+  paned_class->cycle_child_focus = gtk_paned_cycle_child_focus;
+  paned_class->toggle_handle_focus = gtk_paned_toggle_handle_focus;
+  paned_class->move_handle = gtk_paned_move_handle;
+  paned_class->cycle_handle_focus = gtk_paned_cycle_handle_focus;
+  paned_class->accept_position = gtk_paned_accept_position;
+  paned_class->cancel_position = gtk_paned_cancel_position;
 
 
   paned_props[PROP_POSITION] =
@@ -604,87 +607,84 @@ gtk_paned_class_init (GtkPanedClass *class)
                  _gtk_marshal_BOOLEAN__VOID,
                  G_TYPE_BOOLEAN, 0);
 
+  binding_set = gtk_binding_set_by_class (class);
+
   /* F6 and friends */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_F6, 0,
-                                       "cycle-child-focus",
-                                       "(b)", FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_F6, GDK_SHIFT_MASK,
-                                       "cycle-child-focus",
-                                       "(b)", TRUE);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_F6, 0,
+                                "cycle-child-focus", 1, 
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_F6, GDK_SHIFT_MASK,
+                               "cycle-child-focus", 1,
+                               G_TYPE_BOOLEAN, TRUE);
 
   /* F8 and friends */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_F8, 0,
-                                      "cycle-handle-focus",
-                                       "(b)", FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_F8, GDK_SHIFT_MASK,
-                                      "cycle-handle-focus",
-                                       "(b)", TRUE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_F8, 0,
+                               "cycle-handle-focus", 1,
+                               G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_F8, GDK_SHIFT_MASK,
+                               "cycle-handle-focus", 1,
+                               G_TYPE_BOOLEAN, TRUE);
  
-  add_tab_bindings (widget_class, 0);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK);
-  add_tab_bindings (widget_class, GDK_SHIFT_MASK);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
+  add_tab_bindings (binding_set, 0);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK);
+  add_tab_bindings (binding_set, GDK_SHIFT_MASK);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
 
   /* accept and cancel positions */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_Escape, 0,
-                                      "cancel-position",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Return, 0,
-                                       "accept-position",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_ISO_Enter, 0,
-                                       "accept-position",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_KP_Enter, 0,
-                                       "accept-position",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                      GDK_KEY_space, 0,
-                                       "accept-position",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, 0,
-                                       "accept-position",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_Escape, 0,
+                               "cancel-position", 0);
+
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_Return, 0,
+                               "accept-position", 0);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_ISO_Enter, 0,
+                               "accept-position", 0);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_KP_Enter, 0,
+                               "accept-position", 0);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_space, 0,
+                               "accept-position", 0);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KEY_KP_Space, 0,
+                               "accept-position", 0);
 
   /* move handle */
-  add_move_binding (widget_class, GDK_KEY_Left, 0, GTK_SCROLL_STEP_LEFT);
-  add_move_binding (widget_class, GDK_KEY_KP_Left, 0, GTK_SCROLL_STEP_LEFT);
-  add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
-  add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
-
-  add_move_binding (widget_class, GDK_KEY_Right, 0, GTK_SCROLL_STEP_RIGHT);
-  add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
-  add_move_binding (widget_class, GDK_KEY_KP_Right, 0, GTK_SCROLL_STEP_RIGHT);
-  add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
-
-  add_move_binding (widget_class, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
-  add_move_binding (widget_class, GDK_KEY_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
-  add_move_binding (widget_class, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
-  add_move_binding (widget_class, GDK_KEY_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
-  add_move_binding (widget_class, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
-  add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP);
-
-  add_move_binding (widget_class, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
-  add_move_binding (widget_class, GDK_KEY_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
-  add_move_binding (widget_class, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
-  add_move_binding (widget_class, GDK_KEY_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
-  add_move_binding (widget_class, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
-  add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
-
-  add_move_binding (widget_class, GDK_KEY_Home, 0, GTK_SCROLL_START);
-  add_move_binding (widget_class, GDK_KEY_KP_Home, 0, GTK_SCROLL_START);
-  add_move_binding (widget_class, GDK_KEY_End, 0, GTK_SCROLL_END);
-  add_move_binding (widget_class, GDK_KEY_KP_End, 0, GTK_SCROLL_END);
+  add_move_binding (binding_set, GDK_KEY_Left, 0, GTK_SCROLL_STEP_LEFT);
+  add_move_binding (binding_set, GDK_KEY_KP_Left, 0, GTK_SCROLL_STEP_LEFT);
+  add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
+  add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
+
+  add_move_binding (binding_set, GDK_KEY_Right, 0, GTK_SCROLL_STEP_RIGHT);
+  add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
+  add_move_binding (binding_set, GDK_KEY_KP_Right, 0, GTK_SCROLL_STEP_RIGHT);
+  add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
+
+  add_move_binding (binding_set, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
+  add_move_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
+  add_move_binding (binding_set, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
+  add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
+  add_move_binding (binding_set, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+  add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+
+  add_move_binding (binding_set, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
+  add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
+  add_move_binding (binding_set, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
+  add_move_binding (binding_set, GDK_KEY_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
+  add_move_binding (binding_set, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
+  add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
+
+  add_move_binding (binding_set, GDK_KEY_Home, 0, GTK_SCROLL_START);
+  add_move_binding (binding_set, GDK_KEY_KP_Home, 0, GTK_SCROLL_START);
+  add_move_binding (binding_set, GDK_KEY_End, 0, GTK_SCROLL_END);
+  add_move_binding (binding_set, GDK_KEY_KP_End, 0, GTK_SCROLL_END);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_PANED_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("paned"));
index 0ed1fe043f494e501a9e40133a118884226f55e4..f39531639b511a6f091d974aca9f0cd7d4dc004c 100644 (file)
@@ -23,6 +23,7 @@
 #include "gtkpasswordentry.h"
 
 #include "gtkaccessible.h"
+#include "gtkbindings.h"
 #include "gtktextprivate.h"
 #include "gtkeditable.h"
 #include "gtkgestureclick.h"
index 61938f345c6e9495218b8c5e9d99c55be193ba84..b7b431a944dacaaaa9a576e45ef54f337e510a76 100644 (file)
@@ -106,15 +106,7 @@ static void        mount_volume                                  (GtkPlacesView
 static void        on_eject_button_clicked                       (GtkWidget        *widget,
                                                                   GtkPlacesViewRow *row);
 
-static gboolean on_row_popup_menu (GtkWidget *widget,
-                                   GVariant  *args,
-                                   gpointer   user_data);
-
-static void click_cb (GtkGesture *gesture,
-                      int         n_press,
-                      double      x,
-                      double      y,
-                      gpointer    user_data);
+static gboolean    on_row_popup_menu                             (GtkPlacesViewRow *row);
 
 static void        populate_servers                              (GtkPlacesView *view);
 
@@ -681,28 +673,12 @@ insert_row (GtkPlacesView *view,
             gboolean       is_network)
 {
   GtkPlacesViewPrivate *priv;
-  GtkEventController *controller;
-  GtkShortcutTrigger *trigger;
-  GtkShortcutAction *action;
-  GtkShortcut *shortcut;
-  GtkGesture *gesture;
 
   priv = gtk_places_view_get_instance_private (view);
 
   g_object_set_data (G_OBJECT (row), "is-network", GINT_TO_POINTER (is_network));
 
-  controller = gtk_shortcut_controller_new ();
-  trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
-                                         gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
-  action = gtk_callback_action_new (on_row_popup_menu, row, NULL);
-  shortcut = gtk_shortcut_new (trigger, action);
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  gtk_widget_add_controller (GTK_WIDGET (row), controller);
-
-  gesture = gtk_gesture_click_new ();
-  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
-  g_signal_connect (gesture, "pressed", G_CALLBACK (click_cb), row);
-  gtk_widget_add_controller (row, GTK_EVENT_CONTROLLER (gesture));
+  g_signal_connect (row, "popup-menu", G_CALLBACK (on_row_popup_menu), row);
 
   g_signal_connect (gtk_places_view_row_get_eject_button (GTK_PLACES_VIEW_ROW (row)),
                     "clicked",
@@ -1723,12 +1699,10 @@ get_menu_model (void)
   return G_MENU_MODEL (menu);
 }
 
-static gboolean
-on_row_popup_menu (GtkWidget *widget,
-                   GVariant  *args,
-                   gpointer   user_data)
+static void
+popup_menu (GtkPlacesViewRow *row,
+            GdkEventButton   *event)
 {
-  GtkPlacesViewRow *row = GTK_PLACES_VIEW_ROW (widget);
   GtkPlacesViewPrivate *priv;
   GtkWidget *view;
   GMount *mount;
@@ -1756,39 +1730,27 @@ on_row_popup_menu (GtkWidget *widget,
       GMenuModel *model = get_menu_model ();
 
       priv->popup_menu = gtk_popover_menu_new_from_model (model);
+      gtk_widget_set_parent (priv->popup_menu, GTK_WIDGET (view));
       gtk_popover_set_position (GTK_POPOVER (priv->popup_menu), GTK_POS_BOTTOM);
 
       gtk_popover_set_has_arrow (GTK_POPOVER (priv->popup_menu), FALSE);
-      gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_CENTER);
+      gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_START);
 
       g_object_unref (model);
     }
 
-  if (priv->row_for_action)
-    g_object_set_data (G_OBJECT (priv->row_for_action), "menu", NULL);
-
-  g_object_ref (priv->popup_menu);
-  gtk_widget_unparent (priv->popup_menu);
+  gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_CENTER);
   gtk_widget_set_parent (priv->popup_menu, GTK_WIDGET (row));
-  g_object_unref (priv->popup_menu);
 
   priv->row_for_action = row;
-  if (priv->row_for_action)
-    g_object_set_data (G_OBJECT (priv->row_for_action), "menu", priv->popup_menu);
-
   gtk_popover_popup (GTK_POPOVER (priv->popup_menu));
-
-  return TRUE;
 }
 
-static void
-click_cb (GtkGesture *gesture,
-          int         n_press,
-          double      x,
-          double      y,
-          gpointer    user_data)
+static gboolean
+on_row_popup_menu (GtkPlacesViewRow *row)
 {
-  on_row_popup_menu (GTK_WIDGET (user_data), NULL, NULL);
+  popup_menu (row, NULL);
+  return TRUE;
 }
 
 static gboolean
index e3deff9a84870c0580dbd5b150eaf9e25d5f48df..3df575aa424642919cc169a5b68c2d03ffeae6fa 100644 (file)
@@ -35,7 +35,6 @@
 #include "gtkspinner.h"
 #include "gtkstack.h"
 #include "gtktypebuiltins.h"
-#include "gtknative.h"
 #else
 #include <gtk/gtk.h>
 #endif
@@ -194,6 +193,18 @@ measure_available_space (GtkPlacesViewRow *row)
     }
 }
 
+static void
+pressed_cb (GtkGesture       *gesture,
+            int               n_pressed,
+            double            x,
+            double            y,
+            GtkPlacesViewRow *row)
+{
+  gboolean menu_activated;
+
+  g_signal_emit_by_name (row, "popup-menu", &menu_activated);
+}
+
 static void
 gtk_places_view_row_finalize (GObject *object)
 {
@@ -309,19 +320,6 @@ gtk_places_view_row_set_property (GObject      *object,
     }
 }
 
-static void
-gtk_places_view_row_size_allocate (GtkWidget *widget,
-                                   int        width,
-                                   int        height,
-                                   int        baseline)
-{
-  GtkWidget *menu = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "menu"));
-
-  GTK_WIDGET_CLASS (gtk_places_view_row_parent_class)->size_allocate (widget, width, height, baseline);
-  if (menu)
-    gtk_native_check_resize (GTK_NATIVE (menu));
-}
-
 static void
 gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass)
 {
@@ -332,8 +330,6 @@ gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass)
   object_class->get_property = gtk_places_view_row_get_property;
   object_class->set_property = gtk_places_view_row_set_property;
 
-  widget_class->size_allocate = gtk_places_view_row_size_allocate;
-
   properties[PROP_ICON] =
           g_param_spec_object ("icon",
                                P_("Icon of the row"),
@@ -395,6 +391,8 @@ gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, icon_image);
   gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, name_label);
   gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, path_label);
+
+  gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
 }
 
 static void
index 5644413929d745a5391adb514967d6ae8668bef7..ef7253d1235faf0fa27e4b68019733b9cb58792c 100644 (file)
 #include "gtkwidgetprivate.h"
 #include "gtkeventcontrollerkey.h"
 #include "gtkcssnodeprivate.h"
+#include "gtkbindings.h"
 #include "gtkbinlayout.h"
 #include "gtkenums.h"
 #include "gtktypebuiltins.h"
+#include "gtkmnemonichash.h"
 #include "gtkgizmoprivate.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkcssnumbervalueprivate.h"
 #include "gtksnapshot.h"
-#include "gtkshortcut.h"
-#include "gtkshortcuttrigger.h"
 
 #include "gtkrender.h"
 #include "gtkstylecontextprivate.h"
@@ -1445,41 +1445,37 @@ gtk_popover_remove (GtkContainer *container,
 }
 
 static void
-add_tab_bindings (GtkWidgetClass   *widget_class,
+add_tab_bindings (GtkBindingSet    *binding_set,
                   GdkModifierType   modifiers,
                   GtkDirectionType  direction)
 {
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Tab, modifiers,
-                                       "move-focus",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Tab, modifiers,
-                                       "move-focus",
-                                       "(i)", direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
-add_arrow_bindings (GtkWidgetClass   *widget_class,
+add_arrow_bindings (GtkBindingSet    *binding_set,
                     guint             keysym,
                     GtkDirectionType  direction)
 {
   guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
 
-  gtk_widget_class_add_binding_signal (widget_class, keysym, 0,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class, keysym, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, 0,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, 0,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
@@ -1488,6 +1484,7 @@ gtk_popover_class_init (GtkPopoverClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   object_class->dispose = gtk_popover_dispose;
   object_class->finalize = gtk_popover_finalize;
@@ -1566,22 +1563,24 @@ gtk_popover_class_init (GtkPopoverClass *klass)
                   G_TYPE_NONE,
                   0);
 
-  add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
-  add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
-  add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
-  add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
-  add_tab_bindings (widget_class, 0, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
-                                       "activate-default", NULL);
+  binding_set = gtk_binding_set_by_class (klass);
+
+  add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+  add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+  add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+  add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+  add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+                                "activate-default", 0);
 
   gtk_widget_class_set_css_name (widget_class, "popover");
 }
index edfbdb078c3760c3bd5b47bcd95986448dbc7e86..d9779bd2f75c7f7fef1bde0c59147bc7fe02075e 100644 (file)
@@ -32,6 +32,7 @@
 #include "gtkeventcontrollermotion.h"
 #include "gtkmain.h"
 #include "gtktypebuiltins.h"
+#include "gtkbindings.h"
 #include "gtkmodelbuttonprivate.h"
 #include "gtkpopovermenubar.h"
 
@@ -361,37 +362,37 @@ gtk_popover_menu_focus (GtkWidget        *widget,
 
 
 static void
-add_tab_bindings (GtkWidgetClass   *widget_class,
+add_tab_bindings (GtkBindingSet    *binding_set,
                   GdkModifierType   modifiers,
                   GtkDirectionType  direction)
 {
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Tab, modifiers,
-                                       "move-focus",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Tab, modifiers,
-                                       "move-focus",
-                                       "(i)", direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
-add_arrow_bindings (GtkWidgetClass   *widget_class,
+add_arrow_bindings (GtkBindingSet    *binding_set,
                     guint             keysym,
                     GtkDirectionType  direction)
 {
   guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
  
-  gtk_widget_class_add_binding_signal (widget_class, keysym, 0,
-                                       "move-focus",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class, keysym, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, 0,
-                                       "move-focus",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)", direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, 0,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
@@ -407,6 +408,7 @@ gtk_popover_menu_class_init (GtkPopoverMenuClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   object_class->dispose = gtk_popover_menu_dispose;
   object_class->set_property = gtk_popover_menu_set_property;
@@ -433,26 +435,28 @@ gtk_popover_menu_class_init (GtkPopoverMenuClass *klass)
                                                         G_TYPE_MENU_MODEL,
                                                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
-  add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
-  add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
-  add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
-  add_tab_bindings (widget_class, 0, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0,
-                                       "activate-default", NULL);
+  binding_set = gtk_binding_set_by_class (klass);
+
+  add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+  add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+  add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+  add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+  add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+                                "activate-default", 0);
 }
 
 /**
index b2045966500b93646932f14a39320b2e62e86f1e..7ab475d2a39df87f2e32417ed92e665e2670c59c 100644 (file)
@@ -1883,6 +1883,16 @@ gtk_range_click_gesture_pressed (GtkGestureClick *gesture,
       mouse_location == priv->highlight_widget)
     mouse_location = priv->trough_widget;
 
+  if (mouse_location == priv->slider_widget &&
+      gdk_event_triggers_context_menu (event))
+    {
+      gboolean handled;
+
+      gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+      g_signal_emit_by_name (widget, "popup-menu", &handled);
+      return;
+    }
+
   if (mouse_location == priv->slider_widget)
     {
       /* Shift-click in the slider = fine adjustment */
index 3e6a7b78b626a3697ed3aeba7b7fd3055ca0660e..dce284a57f81cfd6c841dc921f6992c375305b61 100644 (file)
@@ -27,8 +27,6 @@
 #include "gtkprivate.h"
 #include "gtkintl.h"
 
-#include "gtkshortcutmanager.h"
-
 /**
  * SECTION:gtkroot
  * @Title: GtkRoot
index 9583c3ea9c632f8041ff94b5c8a263d8b09b083b..244c095251d98ffcd9e48ee2adcecb4151dcd3c9 100644 (file)
@@ -28,6 +28,7 @@
 #include "gtkscale.h"
 
 #include "gtkadjustment.h"
+#include "gtkbindings.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
 #include "gtkgizmoprivate.h"
@@ -622,11 +623,10 @@ gtk_scale_size_allocate (GtkWidget *widget,
     }
 }
 
-#define add_slider_binding(binding_set, keyval, mask, scroll)        \
-  gtk_widget_class_add_binding_signal (widget_class,                 \
-                                       keyval, mask,                 \
-                                       I_("move-slider"),            \
-                                       "(i)", scroll)
+#define add_slider_binding(binding_set, keyval, mask, scroll)              \
+  gtk_binding_entry_add_signal (binding_set, keyval, mask,                 \
+                                I_("move-slider"), 1, \
+                                GTK_TYPE_SCROLL_TYPE, scroll)
 
 static void
 gtk_scale_value_changed (GtkRange *range)
@@ -650,6 +650,7 @@ gtk_scale_class_init (GtkScaleClass *class)
   GObjectClass   *gobject_class;
   GtkWidgetClass *widget_class;
   GtkRangeClass  *range_class;
+  GtkBindingSet  *binding_set;
   
   gobject_class = G_OBJECT_CLASS (class);
   range_class = (GtkRangeClass*) class;
@@ -705,6 +706,8 @@ gtk_scale_class_init (GtkScaleClass *class)
    * blind users etc. don't care about scale orientation.
    */
   
+  binding_set = gtk_binding_set_by_class (class);
+
   add_slider_binding (binding_set, GDK_KEY_Left, 0,
                       GTK_SCROLL_STEP_LEFT);
 
index 76c2173d49c16ee0c50b77bc4951c8c8b8b26b77..3b41e6a64cf460b6d0e775c7bb79dcd8557d054b 100644 (file)
@@ -37,6 +37,7 @@
 #include "gtkscalebutton.h"
 
 #include "gtkadjustment.h"
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkbuttonprivate.h"
 #include "gtkimage.h"
@@ -170,6 +171,7 @@ gtk_scale_button_class_init (GtkScaleButtonClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   gobject_class->constructed = gtk_scale_button_constructed;
   gobject_class->finalize = gtk_scale_button_finalize;
@@ -296,30 +298,20 @@ gtk_scale_button_class_init (GtkScaleButtonClass *klass)
                                 G_TYPE_NONE, 0);
 
   /* Key bindings */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_space, 0,
-                                      "popup",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Space, 0,
-                                      "popup",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Return, 0,
-                                      "popup",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_ISO_Enter, 0,
-                                      "popup",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Enter, 0,
-                                      "popup",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Escape, 0,
-                                      "popdown",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (widget_class);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+                               "popup", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+                               "popup", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+                               "popup", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+                               "popup", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+                               "popup", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
+                               "popdown", 0);
 
   /* Bind class to template
    */
index f97d3d7647ada7dbb34f5d0817d441838b2adfe8..432000ae5f3e2585e27b88c7886ed1c9f00f8e53 100644 (file)
@@ -209,6 +209,16 @@ gtk_scrollbar_class_init (GtkScrollbarClass *class)
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
 }
 
+static gboolean
+emit_popup_menu (GtkWidget *self)
+{
+  gboolean handled;
+
+  g_signal_emit_by_name (self, "popup-menu", &handled);
+
+  return handled;
+}
+
 static void
 gtk_scrollbar_init (GtkScrollbar *self)
 {
@@ -217,6 +227,7 @@ gtk_scrollbar_init (GtkScrollbar *self)
   priv->orientation = GTK_ORIENTATION_HORIZONTAL;
 
   priv->range = g_object_new (GTK_TYPE_RANGE, NULL);
+  g_signal_connect_swapped (priv->range, "popup-menu", G_CALLBACK (emit_popup_menu), self);
   gtk_widget_set_hexpand (priv->range, TRUE);
   gtk_widget_set_vexpand (priv->range, TRUE);
   gtk_widget_set_parent (priv->range, GTK_WIDGET (self));
index 3bb8d023b881d0fbce2fffabfbf45724cbf5d04f..6debc150ae5d4edfadff2a9ab28bae697d82c931 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "gtkadjustment.h"
 #include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
 #include "gtkeventcontrollermotion.h"
 #include "gtkeventcontrollerscroll.h"
 #include "gtkgesturedrag.h"
@@ -412,7 +413,7 @@ static GParamSpec *properties[NUM_PROPERTIES];
 G_DEFINE_TYPE_WITH_PRIVATE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
 
 static void
-add_scroll_binding (GtkWidgetClass *widget_class,
+add_scroll_binding (GtkBindingSet  *binding_set,
                    guint           keyval,
                    GdkModifierType mask,
                    GtkScrollType   scroll,
@@ -420,29 +421,27 @@ add_scroll_binding (GtkWidgetClass *widget_class,
 {
   guint keypad_keyval = keyval - GDK_KEY_Left + GDK_KEY_KP_Left;
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, mask,
-                                       "scroll-child",
-                                       "(ib)", scroll, horizontal);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keypad_keyval, mask,
-                                       "scroll-child",
-                                       "(ib)", scroll, horizontal);
+  gtk_binding_entry_add_signal (binding_set, keyval, mask,
+                                "scroll-child", 2,
+                                GTK_TYPE_SCROLL_TYPE, scroll,
+                               G_TYPE_BOOLEAN, horizontal);
+  gtk_binding_entry_add_signal (binding_set, keypad_keyval, mask,
+                                "scroll-child", 2,
+                                GTK_TYPE_SCROLL_TYPE, scroll,
+                               G_TYPE_BOOLEAN, horizontal);
 }
 
 static void
-add_tab_bindings (GtkWidgetClass   *widget_class,
+add_tab_bindings (GtkBindingSet    *binding_set,
                  GdkModifierType   modifiers,
                  GtkDirectionType  direction)
 {
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Tab, modifiers,
-                                       "move-focus-out",
-                                       "(i)", direction);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Tab, modifiers,
-                                       "move-focus-out",
-                                       "(i)", direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+                                "move-focus-out", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+                                "move-focus-out", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
@@ -518,6 +517,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GtkBindingSet *binding_set;
 
   gobject_class->set_property = gtk_scrolled_window_set_property;
   gobject_class->get_property = gtk_scrolled_window_get_property;
@@ -789,23 +789,25 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 1, GTK_TYPE_POSITION_TYPE);
 
-  add_scroll_binding (widget_class, GDK_KEY_Left,  GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, TRUE);
-  add_scroll_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD,  TRUE);
-  add_scroll_binding (widget_class, GDK_KEY_Up,    GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, FALSE);
-  add_scroll_binding (widget_class, GDK_KEY_Down,  GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD,  FALSE);
+  binding_set = gtk_binding_set_by_class (class);
 
-  add_scroll_binding (widget_class, GDK_KEY_Page_Up,   GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD, TRUE);
-  add_scroll_binding (widget_class, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_FORWARD,  TRUE);
-  add_scroll_binding (widget_class, GDK_KEY_Page_Up,   0,                GTK_SCROLL_PAGE_BACKWARD, FALSE);
-  add_scroll_binding (widget_class, GDK_KEY_Page_Down, 0,                GTK_SCROLL_PAGE_FORWARD,  FALSE);
+  add_scroll_binding (binding_set, GDK_KEY_Left,  GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, TRUE);
+  add_scroll_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD,  TRUE);
+  add_scroll_binding (binding_set, GDK_KEY_Up,    GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, FALSE);
+  add_scroll_binding (binding_set, GDK_KEY_Down,  GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD,  FALSE);
 
-  add_scroll_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START, TRUE);
-  add_scroll_binding (widget_class, GDK_KEY_End,  GDK_CONTROL_MASK, GTK_SCROLL_END,   TRUE);
-  add_scroll_binding (widget_class, GDK_KEY_Home, 0,                GTK_SCROLL_START, FALSE);
-  add_scroll_binding (widget_class, GDK_KEY_End,  0,                GTK_SCROLL_END,   FALSE);
+  add_scroll_binding (binding_set, GDK_KEY_Page_Up,   GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD, TRUE);
+  add_scroll_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_FORWARD,  TRUE);
+  add_scroll_binding (binding_set, GDK_KEY_Page_Up,   0,                GTK_SCROLL_PAGE_BACKWARD, FALSE);
+  add_scroll_binding (binding_set, GDK_KEY_Page_Down, 0,                GTK_SCROLL_PAGE_FORWARD,  FALSE);
 
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+  add_scroll_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START, TRUE);
+  add_scroll_binding (binding_set, GDK_KEY_End,  GDK_CONTROL_MASK, GTK_SCROLL_END,   TRUE);
+  add_scroll_binding (binding_set, GDK_KEY_Home, 0,                GTK_SCROLL_START, FALSE);
+  add_scroll_binding (binding_set, GDK_KEY_End,  0,                GTK_SCROLL_END,   FALSE);
+
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SCROLLED_WINDOW_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("scrolledwindow"));
index 5d92aeebbad85eec6753943a234886496fd6c4a0..535aaf946a1ce7eeec74cc62e61a034f022f20b9 100644 (file)
@@ -30,6 +30,7 @@
 #include "gtksearchentryprivate.h"
 
 #include "gtkaccessible.h"
+#include "gtkbindings.h"
 #include "gtkeditable.h"
 #include "gtkboxlayout.h"
 #include "gtkgestureclick.h"
@@ -266,6 +267,7 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   object_class->finalize = gtk_search_entry_finalize;
   object_class->get_property = gtk_search_entry_get_property;
@@ -399,18 +401,14 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
                   NULL,
                   G_TYPE_NONE, 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_g, GDK_CONTROL_MASK,
-                                       "next-match",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_g, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "previous-match",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Escape, 0,
-                                       "stop-search",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (klass);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
+                                "next-match", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                                "previous-match", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
+                                "stop-search", 0);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
diff --git a/gtk/gtkshortcut.c b/gtk/gtkshortcut.c
deleted file mode 100644 (file)
index 6a7ff1a..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#include "config.h"
-
-#include "gtkshortcut.h"
-
-#include "gtkintl.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkwidget.h"
-
-/**
- * SECTION:gtkshortcut
- * @title: GtkShortcut
- * @short_description: An object describing a keyboard shortcut
- * @see_also: #GtkShortcutController, #GtkShortcutAction,
- *     #GtkShortcutTrigger
- *
- * GtkShortcut is the low level object used for managing keyboard
- * shortcuts.
- *
- * It contains a description of how to trigger the shortcut via a
- * #GtkShortcutTrigger and a way to activate the shortcut on a widget
- * via #GtkShortcutAction.
- *
- * The actual work is usually done via #GtkShortcutController, which
- * decides if and when to activate a shortcut. Using that controller
- * directly however is rarely necessary as various higher level
- * convenience APIs exist on #GtkWidgets that make it easier to use
- * shortcuts in GTK.
- *
- * #GtkShortcut does provide functionality to make it easy for users
- * to work with shortcuts, either by providing informational strings
- * for display purposes or by allowing shortcuts to be configured.
- */
-
-struct _GtkShortcut
-{
-  GObject parent_instance;
-
-  GtkShortcutAction *action;
-  GtkShortcutTrigger *trigger;
-  GVariant *args;
-};
-
-enum
-{
-  PROP_0,
-  PROP_ACTION,
-  PROP_ARGUMENTS,
-  PROP_TRIGGER,
-
-  N_PROPS
-};
-
-G_DEFINE_TYPE (GtkShortcut, gtk_shortcut, G_TYPE_OBJECT)
-
-static GParamSpec *properties[N_PROPS] = { NULL, };
-
-static void
-gtk_shortcut_dispose (GObject *object)
-{
-  GtkShortcut *self = GTK_SHORTCUT (object);
-
-  g_clear_pointer (&self->action, gtk_shortcut_action_unref);
-  g_clear_pointer (&self->trigger, gtk_shortcut_trigger_unref);
-  g_clear_pointer (&self->args, g_variant_unref);
-
-  G_OBJECT_CLASS (gtk_shortcut_parent_class)->dispose (object);
-}
-
-static void
-gtk_shortcut_get_property (GObject    *object,
-                           guint       property_id,
-                           GValue     *value,
-                           GParamSpec *pspec)
-{
-  GtkShortcut *self = GTK_SHORTCUT (object);
-
-  switch (property_id)
-    {
-    case PROP_ACTION:
-      g_value_set_boxed (value, self->action);
-      break;
-
-    case PROP_ARGUMENTS:
-      g_value_set_variant (value, self->args);
-      break;
-
-    case PROP_TRIGGER:
-      g_value_set_boxed (value, self->trigger);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_shortcut_set_property (GObject      *object,
-                           guint         property_id,
-                           const GValue *value,
-                           GParamSpec   *pspec)
-{
-  GtkShortcut *self = GTK_SHORTCUT (object);
-
-  switch (property_id)
-    {
-    case PROP_ACTION:
-      gtk_shortcut_set_action (self, g_value_dup_boxed (value));
-      break;
-
-    case PROP_ARGUMENTS:
-      gtk_shortcut_set_arguments (self, g_value_get_variant (value));
-      break;
-
-    case PROP_TRIGGER:
-      gtk_shortcut_set_trigger (self, g_value_dup_boxed (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_shortcut_class_init (GtkShortcutClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  gobject_class->dispose = gtk_shortcut_dispose;
-  gobject_class->get_property = gtk_shortcut_get_property;
-  gobject_class->set_property = gtk_shortcut_set_property;
-
-  /**
-   * GtkShortcut:action:
-   *
-   * The action that gets activated by this shortcut.
-   */
-  properties[PROP_ACTION] =
-    g_param_spec_boxed ("action",
-                        P_("Action"),
-                        P_("The action activated by this shortcut"),
-                        GTK_TYPE_SHORTCUT_ACTION,
-                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
-  /**
-   * GtkShortcut:arguments:
-   *
-   * Arguments passed to activation.
-   */
-  properties[PROP_ARGUMENTS] =
-    g_param_spec_variant ("arguments",
-                          P_("Arguments"),
-                          P_("Arguments passed to activation"),
-                          G_VARIANT_TYPE_ANY,
-                          NULL,
-                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
-  /**
-   * GtkShortcut:trigger:
-   *
-   * The trigger that triggers this shortcut.
-   */
-  properties[PROP_TRIGGER] =
-    g_param_spec_boxed ("trigger",
-                        P_("Trigger"),
-                        P_("The trigger for this shortcut"),
-                        GTK_TYPE_SHORTCUT_TRIGGER,
-                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
-  g_object_class_install_properties (gobject_class, N_PROPS, properties);
-}
-
-static void
-gtk_shortcut_init (GtkShortcut *self)
-{
-  self->action = gtk_nothing_action_new ();
-  self->trigger = gtk_shortcut_trigger_ref (gtk_never_trigger_get ());
-}
-
-/**
- * gtk_shortcut_new:
- * @trigger: (transfer full) (allow-none): The trigger that will trigger the shortcut
- * @action: (transfer full) (allow-none): The action that will be activated upon
- *    triggering
- *
- * Creates a new #GtkShortcut that is triggered by @trigger and then activates
- * @action.
- *
- * Returns: a new #GtkShortcut
- **/
-GtkShortcut *
-gtk_shortcut_new (GtkShortcutTrigger *trigger,
-                  GtkShortcutAction  *action)
-{
-  GtkShortcut *shortcut;
-
-  shortcut = g_object_new (GTK_TYPE_SHORTCUT,
-                           "action", action,
-                           "trigger", trigger,
-                           NULL);
-
-  if (trigger)
-    gtk_shortcut_trigger_unref (trigger);
-  if (action)
-    gtk_shortcut_action_unref (action);
-
-  return shortcut;
-}
-
-/**
- * gtk_shortcut_new_with_arguments: (skip)
- * @trigger: (transfer full) (allow-none): The trigger that will trigger the shortcut
- * @action: (transfer full) (allow-none): The action that will be activated upon
- *    triggering
- * @format_string: (allow-none): GVariant format string for arguments or %NULL for
- *     no arguments
- * @...: arguments, as given by format string.
- *
- * Creates a new #GtkShortcut that is triggered by @trigger and then activates
- * @action with arguments given by @format_string.
- *
- * Returns: a new #GtkShortcut
- **/
-GtkShortcut *
-gtk_shortcut_new_with_arguments (GtkShortcutTrigger *trigger,
-                                 GtkShortcutAction  *action,
-                                 const gchar        *format_string,
-                                 ...)
-{
-  GtkShortcut *shortcut;
-  GVariant *args;
-
-  if (format_string)
-    {
-      va_list valist;
-      va_start (valist, format_string);
-      args = g_variant_new_va (format_string, NULL, &valist);
-      va_end (valist);
-    }
-  else
-    {
-      args = NULL;
-    }
-
-  shortcut = g_object_new (GTK_TYPE_SHORTCUT,
-                           "action", action,
-                           "arguments", args,
-                           "trigger", trigger,
-                           NULL);
-
-  if (trigger)
-    gtk_shortcut_trigger_unref (trigger);
-  if (action)
-    gtk_shortcut_action_unref (action);
-
-  return shortcut;
-}
-
-/**
- * gtk_shortcut_get_action:
- * @self: a #GtkShortcut
- *
- * Gets the action that is activated by this shortcut.
- *
- * Returns: (transfer none): the action
- **/
-GtkShortcutAction *
-gtk_shortcut_get_action (GtkShortcut *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
-
-  return self->action;
-}
-
-/**
- * gtk_shortcut_set_action:
- * @self: a #GtkShortcut
- * @action: (transfer full) (nullable): The new action.
- *     If the @action is %NULL, the nothing action will be used.
- *
- * Sets the new action for @self to be @action.
- **/
-void
-gtk_shortcut_set_action (GtkShortcut *self,
-                         GtkShortcutAction *action)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT (self));
-
-  if (action == NULL)
-    action = gtk_nothing_action_new ();
-
-  if (self->action == action)
-    {
-      gtk_shortcut_action_unref (action);
-      return;
-    }
-  
-  gtk_shortcut_action_unref (self->action);
-  self->action = action;
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTION]);
-}
-
-/**
- * gtk_shortcut_get_trigger:
- * @self: a #GtkShortcut
- *
- * Gets the trigger used to trigger @self.
- *
- * Returns: (transfer none): the trigger used
- **/
-GtkShortcutTrigger *
-gtk_shortcut_get_trigger (GtkShortcut *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
-
-  return self->trigger;
-}
-
-/**
- * gtk_shortcut_set_trigger:
- * @self: a #GtkShortcut
- * @trigger: (transfer full) (nullable): The new trigger.
- *     If the @trigger is %NULL, the never trigger will be used.
- *
- * Sets the new trigger for @self to be @trigger.
- **/
-void
-gtk_shortcut_set_trigger (GtkShortcut *self,
-                          GtkShortcutTrigger *trigger)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT (self));
-
-  if (trigger == NULL)
-    trigger = gtk_shortcut_trigger_ref (gtk_never_trigger_get ());
-
-  if (self->trigger == trigger)
-    {
-      gtk_shortcut_trigger_unref (trigger);
-      return;
-    }
-  
-  gtk_shortcut_trigger_unref (self->trigger);
-  self->trigger = trigger;
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRIGGER]);
-}
-
-GVariant *
-gtk_shortcut_get_arguments (GtkShortcut *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
-
-  return self->args;
-}
-
-void
-gtk_shortcut_set_arguments (GtkShortcut *self,
-                            GVariant    *args)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT (self));
-
-  if (self->args == args)
-    return;
-  
-  g_clear_pointer (&self->args, g_variant_unref);
-  if (args)
-    self->args = g_variant_ref_sink (args);
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARGUMENTS]);
-}
diff --git a/gtk/gtkshortcut.h b/gtk/gtkshortcut.h
deleted file mode 100644 (file)
index 77c8975..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_H__
-#define __GTK_SHORTCUT_H__
-
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT         (gtk_shortcut_get_type ())
-
-GDK_AVAILABLE_IN_ALL
-G_DECLARE_FINAL_TYPE (GtkShortcut, gtk_shortcut, GTK, SHORTCUT, GObject)
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcut *   gtk_shortcut_new                                (GtkShortcutTrigger     *trigger,
-                                                                 GtkShortcutAction      *action);
-GDK_AVAILABLE_IN_ALL
-GtkShortcut *   gtk_shortcut_new_with_arguments                 (GtkShortcutTrigger     *trigger,
-                                                                 GtkShortcutAction      *action,
-                                                                 const gchar            *format_string,
-                                                                 ...);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *
-                gtk_shortcut_get_trigger                        (GtkShortcut            *self);
-GDK_AVAILABLE_IN_ALL
-void            gtk_shortcut_set_trigger                        (GtkShortcut            *self,
-                                                                 GtkShortcutTrigger     *trigger);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *
-                gtk_shortcut_get_action                         (GtkShortcut            *self);
-GDK_AVAILABLE_IN_ALL
-void            gtk_shortcut_set_action                         (GtkShortcut            *self,
-                                                                 GtkShortcutAction      *action);
-
-GDK_AVAILABLE_IN_ALL
-GVariant *      gtk_shortcut_get_arguments                      (GtkShortcut            *self);
-GDK_AVAILABLE_IN_ALL
-void            gtk_shortcut_set_arguments                      (GtkShortcut            *self,
-                                                                 GVariant               *args);
-
-G_END_DECLS
-
-#endif  /* __GTK_SHORTCUT_H__ */
diff --git a/gtk/gtkshortcutaction.c b/gtk/gtkshortcutaction.c
deleted file mode 100644 (file)
index 86f59e7..0000000
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-/**
- * SECTION:gtkshortcutaction
- * @Title: GtkShortcutAction
- * @Short_description: Tracking if shortcuts should be activated
- * @See_also: #GtkShortcut
- *
- * #GtkShortcutAction is the object used to track if a #GtkShortcut should be
- * activated. For this purpose, gtk_shortcut_action_action() can be called
- * on a #GdkEvent.
- *
- * #GtkShortcutActions contain functions that allow easy presentation to end
- * users as well as being printed for debugging.
- *
- * All #GtkShortcutActions are immutable, you can only specify their properties
- * during construction. If you want to change a action, you have to replace it
- * with a new one.
- */
-
-#include "config.h"
-
-#include "gtkshortcutactionprivate.h"
-
-#include "gtkbuilder.h"
-#include "gtkwidgetprivate.h"
-
-typedef struct _GtkShortcutActionClass GtkShortcutActionClass;
-
-#define GTK_IS_SHORTCUT_ACTION_TYPE(action,type) (GTK_IS_SHORTCUT_ACTION (action) && (action)->action_class->action_type == (type))
-
-struct _GtkShortcutAction
-{
-  const GtkShortcutActionClass *action_class;
-
-  gatomicrefcount ref_count;
-};
-
-struct _GtkShortcutActionClass
-{
-  GtkShortcutActionType action_type;
-  gsize struct_size;
-  const char *type_name;
-
-  void            (* finalize)    (GtkShortcutAction            *action);
-  gboolean        (* activate)    (GtkShortcutAction            *action,
-                                   GtkShortcutActionFlags        flags,
-                                   GtkWidget                    *widget,
-                                   GVariant                     *args);
-  void            (* print)       (GtkShortcutAction            *action,
-                                   GString                      *string);
-};
-
-G_DEFINE_BOXED_TYPE (GtkShortcutAction, gtk_shortcut_action,
-                     gtk_shortcut_action_ref,
-                     gtk_shortcut_action_unref)
-
-static void
-gtk_shortcut_action_finalize (GtkShortcutAction *self)
-{
-  self->action_class->finalize (self);
-
-  g_free (self);
-}
-
-/*< private >
- * gtk_shortcut_action_new:
- * @action_class: class structure for this action
- *
- * Returns: (transfer full): the newly created #GtkShortcutAction
- */
-static GtkShortcutAction *
-gtk_shortcut_action_new (const GtkShortcutActionClass *action_class)
-{
-  GtkShortcutAction *self;
-
-  g_return_val_if_fail (action_class != NULL, NULL);
-
-  self = g_malloc0 (action_class->struct_size);
-  g_atomic_ref_count_init (&self->ref_count);
-
-  self->action_class = action_class;
-
-  return self;
-}
-
-/**
- * gtk_shortcut_action_ref:
- * @self: a #GtkShortcutAction
- *
- * Acquires a reference on the given #GtkShortcutAction.
- *
- * Returns: (transfer full): the #GtkShortcutAction with an additional reference
- */
-GtkShortcutAction *
-gtk_shortcut_action_ref (GtkShortcutAction *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), NULL);
-
-  g_atomic_ref_count_inc (&self->ref_count);
-
-  return self;
-}
-
-/**
- * gtk_shortcut_action_unref:
- * @self: (transfer full): a #GtkShortcutAction
- *
- * Releases a reference on the given #GtkShortcutAction.
- *
- * If the reference was the last, the resources associated to the @action are
- * freed.
- */
-void
-gtk_shortcut_action_unref (GtkShortcutAction *self)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT_ACTION (self));
-
-  if (g_atomic_ref_count_dec (&self->ref_count))
-    gtk_shortcut_action_finalize (self);
-}
-
-/**
- * gtk_shortcut_action_get_action_type:
- * @self: a #GtkShortcutAction
- *
- * Returns the type of the @action.
- *
- * Returns: the type of the #GtkShortcutAction
- */
-GtkShortcutActionType
-gtk_shortcut_action_get_action_type (GtkShortcutAction *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), GTK_SHORTCUT_ACTION_NOTHING);
-
-  return self->action_class->action_type;
-}
-
-/**
- * gtk_shortcut_action_to_string:
- * @self: a #GtkShortcutAction
- *
- * Prints the given action into a human-readable string.
- * This is a small wrapper around gtk_shortcut_action_print() to help
- * when debugging.
- *
- * Returns: (transfer full): a new string
- **/
-char *
-gtk_shortcut_action_to_string (GtkShortcutAction *self)
-{
-  GString *string;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), NULL);
-
-  string = g_string_new (NULL);
-  gtk_shortcut_action_print (self, string);
-
-  return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_shortcut_action_print:
- * @self: a #GtkShortcutAction
- * @string: a #GString to print into
- *
- * Prints the given action into a string for the developer.
- * This is meant for debugging and logging.
- *
- * The form of the representation may change at any time and is
- * not guaranteed to stay identical.
- **/
-void
-gtk_shortcut_action_print (GtkShortcutAction *self,
-                           GString           *string)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT_ACTION (self));
-  g_return_if_fail (string != NULL);
-
-  return self->action_class->print (self, string);
-}
-
-/**
- * gtk_shortcut_action_activate:
- * @self: a #GtkShortcutAction
- * @flags: flags to activate with
- * @widget: Target of the activation
- * @args: (allow-none): arguments to pass
- *
- * Activates the action on the @widget with the given @args. 
- *
- * Note that some actions do ignore the passed in @flags, @widget or
- * @args.
- *
- * Activation of an action can fail for various reasons. If the action
- * is not supported by the @widget, if the @args don't match the action
- * or if the activation otherwise had no effect, %FALSE will be returned.
- *
- * Returns: %TRUE if this action was activated successfully
- **/
-gboolean
-gtk_shortcut_action_activate (GtkShortcutAction      *self,
-                              GtkShortcutActionFlags  flags,
-                              GtkWidget              *widget,
-                              GVariant               *args)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), FALSE);
-  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-
-  return self->action_class->activate (self, flags, widget, args);
-}
-
-static char *
-string_is_function (const char *string,
-                    const char *function_name)
-{
-  gsize len;
-
-  if (!g_str_has_prefix (string, function_name))
-    return NULL;
-  string += strlen (function_name);
-
-  if (string[0] != '(')
-    return NULL;
-  string ++;
-
-  len = strlen (string);
-  if (len == 0 || string[len - 1] != ')')
-    return NULL;
-
-  return g_strndup (string, len - 1);
-}
-
-GtkShortcutAction *
-gtk_shortcut_action_parse_builder (GtkBuilder  *builder,
-                                   const char  *string,
-                                   GError     **error)
-{
-  GtkShortcutAction *result;
-  char *arg;
-
-  if (g_str_equal (string, "nothing"))
-    return gtk_nothing_action_new ();
-  if (g_str_equal (string, "activate"))
-    return gtk_activate_action_new ();
-  if (g_str_equal (string, "mnemonic-activate"))
-    return gtk_mnemonic_action_new ();
-
-  if ((arg = string_is_function (string, "action")))
-    {
-      result = gtk_action_action_new (arg);
-      g_free (arg);
-    }
-  else if ((arg = string_is_function (string, "signal")))
-    {
-      result = gtk_signal_action_new (arg);
-      g_free (arg);
-    }
-  else if ((arg = string_is_function (string, "gaction")))
-    {
-      GObject *object = gtk_builder_get_object (builder, arg);
-
-      if (object == NULL)
-        {
-          g_set_error (error,
-                       GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_ID,
-                       "Action with ID \"%s\" not found", arg);
-          g_free (arg);
-          return NULL;
-        }
-      else if (!G_IS_ACTION (object))
-        {
-          g_set_error (error,
-                       GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_ID,
-                       "Object with ID \"%s\" is not a GAction", arg);
-          g_free (arg);
-          return NULL;
-        }
-
-      result = gtk_gaction_action_new (G_ACTION (object));
-      g_free (arg);
-    }
-  else
-    {
-      g_set_error (error,
-                   GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
-                   "String \"%s\" does not specify a GtkShortcutAction", string);
-      return NULL;
-    }
-
-  return result;
-}
-
-/*** GTK_SHORTCUT_ACTION_NOTHING ***/
-
-typedef struct _GtkNothingAction GtkNothingAction;
-
-struct _GtkNothingAction
-{
-  GtkShortcutAction action;
-};
-
-static void
-gtk_nothing_action_finalize (GtkShortcutAction *action)
-{
-  g_assert_not_reached ();
-}
-
-static gboolean
-gtk_nothing_action_activate (GtkShortcutAction      *action,
-                             GtkShortcutActionFlags  flags,
-                             GtkWidget              *widget,
-                             GVariant               *args)
-{
-  return FALSE;
-}
-
-static void
-gtk_nothing_action_print (GtkShortcutAction *action,
-                          GString           *string)
-{
-  g_string_append (string, "nothing");
-}
-
-static const GtkShortcutActionClass GTK_NOTHING_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_NOTHING,
-  sizeof (GtkNothingAction),
-  "GtkNothingAction",
-  gtk_nothing_action_finalize,
-  gtk_nothing_action_activate,
-  gtk_nothing_action_print
-};
-
-static GtkNothingAction nothing = { { &GTK_NOTHING_ACTION_CLASS, 1 } };
-
-/**
- * gtk_nothing_action_new:
- *
- * Gets the nothing action. This is an action that does nothing and where
- * activating it always fails.
- *
- * Returns: The nothing action
- */
-GtkShortcutAction *
-gtk_nothing_action_new (void)
-{
-  return gtk_shortcut_action_ref (&nothing.action);
-}
-
-/*** GTK_SHORTCUT_ACTION_CALLBACK ***/
-
-typedef struct _GtkCallbackAction GtkCallbackAction;
-
-struct _GtkCallbackAction
-{
-  GtkShortcutAction action;
-
-  GtkShortcutFunc callback;
-  gpointer user_data;
-  GDestroyNotify destroy_notify;
-};
-
-static void
-gtk_callback_action_finalize (GtkShortcutAction *action)
-{
-  GtkCallbackAction *self = (GtkCallbackAction *) action;
-
-  if (self->destroy_notify)
-    self->destroy_notify (self->user_data);
-}
-
-static gboolean
-gtk_callback_action_activate (GtkShortcutAction      *action,
-                              GtkShortcutActionFlags  flags,
-                              GtkWidget              *widget,
-                              GVariant               *args)
-{
-  GtkCallbackAction *self = (GtkCallbackAction *) action;
-
-  return self->callback (widget, args, self->user_data);
-}
-
-static void
-gtk_callback_action_print (GtkShortcutAction *action,
-                           GString           *string)
-{
-  GtkCallbackAction *self = (GtkCallbackAction *) action;
-
-  g_string_append_printf (string, "callback(%p)", self->callback);
-}
-
-static const GtkShortcutActionClass GTK_CALLBACK_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_CALLBACK,
-  sizeof (GtkCallbackAction),
-  "GtkCallbackAction",
-  gtk_callback_action_finalize,
-  gtk_callback_action_activate,
-  gtk_callback_action_print
-};
-
-/**
- * gtk_callback_action_new:
- * @callback: the callback to call
- * @data: 
- * @destroy: 
- *
- * Create a custom action that calls the given @callback when
- * activated.
- *
- * Returns: A new shortcut action
- **/
-GtkShortcutAction *
-gtk_callback_action_new (GtkShortcutFunc         callback,
-                         gpointer                data,
-                         GDestroyNotify          destroy)
-{
-  GtkCallbackAction *self;
-
-  g_return_val_if_fail (callback != NULL, NULL);
-
-  self = (GtkCallbackAction *) gtk_shortcut_action_new (&GTK_CALLBACK_ACTION_CLASS);
-
-  self->callback = callback;
-  self->user_data = data;
-  self->destroy_notify = destroy;
-
-  return &self->action;
-}
-
-/*** GTK_SHORTCUT_ACTION_ACTIVATE ***/
-
-typedef struct _GtkActivateAction GtkActivateAction;
-
-struct _GtkActivateAction
-{
-  GtkShortcutAction action;
-};
-
-static void
-gtk_activate_action_finalize (GtkShortcutAction *action)
-{
-  g_assert_not_reached ();
-}
-
-static gboolean
-gtk_activate_action_activate (GtkShortcutAction      *action,
-                             GtkShortcutActionFlags  flags,
-                             GtkWidget              *widget,
-                             GVariant               *args)
-{
-  return gtk_widget_activate (widget);
-}
-
-static void
-gtk_activate_action_print (GtkShortcutAction *action,
-                           GString           *string)
-{
-  g_string_append (string, "activate");
-}
-
-static const GtkShortcutActionClass GTK_ACTIVATE_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_ACTIVATE,
-  sizeof (GtkActivateAction),
-  "GtkActivateAction",
-  gtk_activate_action_finalize,
-  gtk_activate_action_activate,
-  gtk_activate_action_print
-};
-
-static GtkActivateAction activate = { { &GTK_ACTIVATE_ACTION_CLASS, 1 } };
-
-/**
- * gtk_activate_action_new:
- *
- * Gets the activate action. This is an action that calls gtk_widget_activate()
- * on the given widget upon activation.
- *
- * Returns: The activate action
- */
-GtkShortcutAction *
-gtk_activate_action_new (void)
-{
-  return gtk_shortcut_action_ref (&activate.action);
-}
-
-/*** GTK_SHORTCUT_ACTION_MNEMONIC ***/
-
-typedef struct _GtkMnemonicAction GtkMnemonicAction;
-
-struct _GtkMnemonicAction
-{
-  GtkShortcutAction action;
-};
-
-static void
-gtk_mnemonic_action_finalize (GtkShortcutAction *action)
-{
-  g_assert_not_reached ();
-}
-
-static gboolean
-gtk_mnemonic_action_activate (GtkShortcutAction      *action,
-                              GtkShortcutActionFlags  flags,
-                              GtkWidget              *widget,
-                              GVariant               *args)
-{
-  return gtk_widget_mnemonic_activate (widget, flags & GTK_SHORTCUT_ACTION_EXCLUSIVE ? FALSE : TRUE);
-}
-
-static void
-gtk_mnemonic_action_print (GtkShortcutAction *action,
-                           GString           *string)
-{
-  g_string_append (string, "mnemonic-activate");
-}
-
-static const GtkShortcutActionClass GTK_MNEMONIC_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_MNEMONIC,
-  sizeof (GtkMnemonicAction),
-  "GtkMnemonicAction",
-  gtk_mnemonic_action_finalize,
-  gtk_mnemonic_action_activate,
-  gtk_mnemonic_action_print
-};
-
-static GtkMnemonicAction mnemonic = { { &GTK_MNEMONIC_ACTION_CLASS, 1 } };
-
-/**
- * gtk_mnemonic_action_new:
- *
- * Gets the mnemonic action. This is an action that calls
- * gtk_widget_mnemonic_activate() on the given widget upon activation.
- *
- * Returns: The mnemonic action
- */
-GtkShortcutAction *
-gtk_mnemonic_action_new (void)
-{
-  return gtk_shortcut_action_ref (&mnemonic.action);
-}
-
-/*** GTK_SHORTCUT_ACTION_SIGNAL ***/
-
-typedef struct _GtkSignalAction GtkSignalAction;
-
-struct _GtkSignalAction
-{
-  GtkShortcutAction action;
-
-  char *name;
-};
-
-static void
-gtk_signal_action_finalize (GtkShortcutAction *action)
-{
-  GtkSignalAction *self = (GtkSignalAction *) action;
-
-  g_free (self->name);
-}
-
-static gboolean
-binding_compose_params (GtkWidget     *widget,
-                        GVariantIter  *args,
-                        GSignalQuery  *query,
-                        GValue       **params_p)
-{
-  GValue *params;
-  const GType *types;
-  guint i;
-  gboolean valid;
-
-  params = g_new0 (GValue, query->n_params + 1);
-  *params_p = params;
-
-  /* The instance we emit on is the first object in the array
-   */
-  g_value_init (params, G_TYPE_OBJECT);
-  g_value_set_object (params, G_OBJECT (widget));
-  params++;
-
-  types = query->param_types;
-  valid = TRUE;
-  for (i = 1; i < query->n_params + 1 && valid; i++)
-    {
-      GValue tmp_value = G_VALUE_INIT;
-      GVariant *tmp_variant;
-
-      g_value_init (params, *types);
-      tmp_variant = g_variant_iter_next_value (args);
-
-      switch ((guint) g_variant_classify (tmp_variant))
-        {
-        case G_VARIANT_CLASS_BOOLEAN:
-          g_value_init (&tmp_value, G_TYPE_BOOLEAN);
-          g_value_set_boolean (&tmp_value, g_variant_get_boolean (tmp_variant));
-          break;
-        case G_VARIANT_CLASS_DOUBLE:
-          g_value_init (&tmp_value, G_TYPE_DOUBLE);
-          g_value_set_double (&tmp_value, g_variant_get_double (tmp_variant));
-          break;
-        case G_VARIANT_CLASS_INT32:
-          g_value_init (&tmp_value, G_TYPE_LONG);
-          g_value_set_long (&tmp_value, g_variant_get_int32 (tmp_variant));
-          break;
-        case G_VARIANT_CLASS_UINT32:
-          g_value_init (&tmp_value, G_TYPE_LONG);
-          g_value_set_long (&tmp_value, g_variant_get_uint32 (tmp_variant));
-          break;
-        case G_VARIANT_CLASS_INT64:
-          g_value_init (&tmp_value, G_TYPE_LONG);
-          g_value_set_long (&tmp_value, g_variant_get_int64 (tmp_variant));
-          break;
-        case G_VARIANT_CLASS_STRING:
-          /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
-           * that since we don't have a GParamSpec, so just do something simple
-           */
-          if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
-            {
-              GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
-              GEnumValue *enum_value;
-              const char *s = g_variant_get_string (tmp_variant, NULL);
-
-              valid = FALSE;
-
-              enum_value = g_enum_get_value_by_name (class, s);
-              if (!enum_value)
-                enum_value = g_enum_get_value_by_nick (class, s);
-
-              if (enum_value)
-                {
-                  g_value_init (&tmp_value, *types);
-                  g_value_set_enum (&tmp_value, enum_value->value);
-                  valid = TRUE;
-                }
-
-              g_type_class_unref (class);
-            }
-          /* This is just a hack for compatibility with GTK+-1.2 where a string
-           * could be used for a single flag value / without the support for multiple
-           * values in gtk_rc_parse_flags(), this isn't very useful.
-           */
-          else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
-            {
-              GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
-              GFlagsValue *flags_value;
-              const char *s = g_variant_get_string (tmp_variant, NULL);
-
-              valid = FALSE;
-
-              flags_value = g_flags_get_value_by_name (class, s);
-              if (!flags_value)
-                flags_value = g_flags_get_value_by_nick (class, s);
-              if (flags_value)
-                {
-                  g_value_init (&tmp_value, *types);
-                  g_value_set_flags (&tmp_value, flags_value->value);
-                  valid = TRUE;
-                }
-
-              g_type_class_unref (class);
-            }
-          else
-            {
-              g_value_init (&tmp_value, G_TYPE_STRING);
-              g_value_set_static_string (&tmp_value, g_variant_get_string (tmp_variant, NULL));
-            }
-          break;
-        default:
-          valid = FALSE;
-          break;
-        }
-
-      if (valid)
-        {
-          if (!g_value_transform (&tmp_value, params))
-            valid = FALSE;
-
-          g_value_unset (&tmp_value);
-        }
-
-      g_variant_unref (tmp_variant);
-      types++;
-      params++;
-    }
-
-  if (!valid)
-    {
-      guint j;
-
-      for (j = 0; j < i; j++)
-        g_value_unset (&(*params_p)[j]);
-
-      g_free (*params_p);
-      *params_p = NULL;
-    }
-
-  return valid;
-}
-
-static gboolean
-gtk_signal_action_emit_signal (GtkWidget *widget,
-                               const char *signal,
-                               GVariant   *args,
-                               gboolean   *handled,
-                               GError    **error)
-{
-  GSignalQuery query;
-  guint signal_id;
-  GValue *params = NULL;
-  GValue return_val = G_VALUE_INIT;
-  GVariantIter args_iter;
-  gsize n_args;
-  guint i;
-
-  *handled = FALSE;
-
-  signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (widget));
-  if (!signal_id)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Could not find signal \"%s\" in the '%s' class ancestry",
-                   signal,
-                   g_type_name (G_OBJECT_TYPE (widget)));
-      return FALSE;
-    }
-
-  g_signal_query (signal_id, &query);
-  if (args == NULL)
-    n_args = 0;
-  else if (g_variant_is_of_type (args, G_VARIANT_TYPE_TUPLE))
-    n_args = g_variant_iter_init (&args_iter, args);
-  else
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "argument GVariant is not a tuple");
-      return FALSE;
-    }
-  if (query.n_params != n_args ||
-      (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) ||
-      !binding_compose_params (widget, &args_iter, &query, &params))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "signature mismatch for signal \"%s\" in the '%s' class ancestry",
-                   signal,
-                   g_type_name (G_OBJECT_TYPE (widget)));
-      return FALSE;
-    }
-  else if (!(query.signal_flags & G_SIGNAL_ACTION))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "signal \"%s\" in the '%s' class ancestry cannot be used for action emissions",
-                   signal,
-                   g_type_name (G_OBJECT_TYPE (widget)));
-      return FALSE;
-    }
-
-  if (query.return_type == G_TYPE_BOOLEAN)
-    g_value_init (&return_val, G_TYPE_BOOLEAN);
-
-  g_signal_emitv (params, signal_id, 0, &return_val);
-
-  if (query.return_type == G_TYPE_BOOLEAN)
-    {
-      if (g_value_get_boolean (&return_val))
-        *handled = TRUE;
-      g_value_unset (&return_val);
-    }
-  else
-    *handled = TRUE;
-
-  if (params != NULL)
-    {
-      for (i = 0; i < query.n_params + 1; i++)
-        g_value_unset (&params[i]);
-
-      g_free (params);
-    }
-
-  return TRUE;
-}
-
-static gboolean
-gtk_signal_action_activate (GtkShortcutAction      *action,
-                            GtkShortcutActionFlags  flags,
-                            GtkWidget              *widget,
-                            GVariant               *args)
-{
-  GtkSignalAction *self = (GtkSignalAction *) action;
-  GError *error = NULL;
-  gboolean handled;
-
-  if (!gtk_signal_action_emit_signal (widget,
-                                      self->name,
-                                      args,
-                                      &handled,
-                                      &error))
-    {
-      g_warning ("gtk_signal_action_activate(): %s",
-                 error->message);
-      g_clear_error (&error);
-      return FALSE;
-    }
-
-  return handled;
-}
-
-static void
-gtk_signal_action_print (GtkShortcutAction *action,
-                         GString           *string)
-{
-  GtkSignalAction *self = (GtkSignalAction *) action;
-
-  g_string_append_printf (string, "signal(%s)", self->name);
-}
-
-static const GtkShortcutActionClass GTK_SIGNAL_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_SIGNAL,
-  sizeof (GtkSignalAction),
-  "GtkSignalAction",
-  gtk_signal_action_finalize,
-  gtk_signal_action_activate,
-  gtk_signal_action_print
-};
-
-/**
- * gtk_signal_action_new:
- * @signal_name: name of the signal to emit
- *
- * Creates an action that when activated, emits the given action signal
- * on the provided widget unpacking the given args into arguments passed
- * to the signal.
- *
- * Returns: a new #GtkShortcutAction
- **/
-GtkShortcutAction *
-gtk_signal_action_new (const char *signal_name)
-{
-  GtkSignalAction *self;
-
-  g_return_val_if_fail (signal_name != NULL, NULL);
-
-  self = (GtkSignalAction *) gtk_shortcut_action_new (&GTK_SIGNAL_ACTION_CLASS);
-
-  self->name = g_strdup (signal_name);
-
-  return &self->action;
-}
-
-/**
- * gtk_signal_action_get_signal_name:
- * @action: a signal action
- *
- * Returns the name of the signal that will be emitted.
- *
- * Returns: the name of the signal to emit
- **/
-const char *
-gtk_signal_action_get_signal_name (GtkShortcutAction *action)
-{
-  GtkSignalAction *self = (GtkSignalAction *) action;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION_TYPE (action, GTK_SHORTCUT_ACTION_SIGNAL), NULL);
-
-  return self->name;
-}
-
-/*** GTK_SHORTCUT_ACTION_ACTION ***/
-
-typedef struct _GtkActionAction GtkActionAction;
-
-struct _GtkActionAction
-{
-  GtkShortcutAction action;
-
-  char *name;
-};
-
-static void
-gtk_action_action_finalize (GtkShortcutAction *action)
-{
-  GtkSignalAction *self = (GtkSignalAction *) action;
-
-  g_free (self->name);
-}
-
-static gboolean
-gtk_shortcut_trigger_check_parameter_type (GVariant           *args,
-                                           const GVariantType *parameter_type)
-{
-  if (args)
-    {
-      if (parameter_type == NULL)
-        {
-          g_warning ("Trying to invoke action with arguments, but action has no parameter");
-          return FALSE;
-        }
-
-      if (!g_variant_is_of_type (args, parameter_type))
-        {
-          gchar *typestr = g_variant_type_dup_string (parameter_type);
-          gchar *targetstr = g_variant_print (args, TRUE);
-          g_warning ("Trying to invoke action with target '%s',"
-                     " but action expects parameter with type '%s'", targetstr, typestr);
-          g_free (targetstr);
-          g_free (typestr);
-          return FALSE;
-        }
-    }
-  else
-    {
-      if (parameter_type != NULL)
-        {
-          gchar *typestr = g_variant_type_dup_string (parameter_type);
-          g_warning ("Trying to invoke action without arguments,"
-                     " but action expects parameter with type '%s'", typestr);
-          g_free (typestr);
-          return FALSE;
-        }
-    }
-
-  return TRUE;
-}
-
-static gboolean
-gtk_action_action_activate (GtkShortcutAction      *action,
-                            GtkShortcutActionFlags  flags,
-                            GtkWidget              *widget,
-                            GVariant               *args)
-{
-  GtkSignalAction *self = (GtkSignalAction *) action;
-  GActionGroup *action_group;
-  const GVariantType *parameter_type;
-  gboolean enabled;
-
-  action_group = G_ACTION_GROUP (_gtk_widget_get_action_muxer (widget, FALSE));
-  if (action_group == NULL)
-    return FALSE;
-
-  if (!g_action_group_query_action (action_group, self->name, &enabled, &parameter_type, NULL, NULL, NULL))
-    return FALSE;
-
-  if (!enabled)
-    return FALSE;
-
-  /* We found an action with the correct name and it's enabled.
-   * This is the action that we are going to try to invoke.
-   *
-   * There is still the possibility that the args don't
-   * match the expected parameter type.  In that case, we will print
-   * a warning.
-   */
-  if (!gtk_shortcut_trigger_check_parameter_type (args, parameter_type))
-    return FALSE;
-
-  g_action_group_activate_action (action_group, self->name, args);
-
-  return TRUE;
-}
-
-static void
-gtk_action_action_print (GtkShortcutAction *action,
-                         GString           *string)
-{
-  GtkActionAction *self = (GtkActionAction *) action;
-
-  g_string_append_printf (string, "action(%s)", self->name);
-}
-
-static const GtkShortcutActionClass GTK_ACTION_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_ACTION,
-  sizeof (GtkActionAction),
-  "GtkActionAction",
-  gtk_action_action_finalize,
-  gtk_action_action_activate,
-  gtk_action_action_print
-};
-
-/**
- * gtk_action_action_new:
- * @name: the detailed name of the action
- *
- * Creates an action that when activated, activates the action given by
- * the detailed @name on the widget passing the given arguments to it.
- *
- * See gtk_widget_insert_action_group() for how to add actions to widgets.
- *
- * Returns: a new #GtkShortcutAction
- **/
-GtkShortcutAction *
-gtk_action_action_new (const char *name)
-{
-  GtkActionAction *self;
-
-  g_return_val_if_fail (name != NULL, NULL);
-
-  self = (GtkActionAction *) gtk_shortcut_action_new (&GTK_ACTION_ACTION_CLASS);
-
-  self->name = g_strdup (name);
-
-  return &self->action;
-}
-
-/**
- * gtk_action_action_get_name:
- * @action: an action action
- *
- * Returns the name of the action that will be activated.
- *
- * Returns: the name of the action to activate
- **/
-const char *
-gtk_action_action_get_name (GtkShortcutAction *action)
-{
-  GtkActionAction *self = (GtkActionAction *) action;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION_TYPE (action, GTK_SHORTCUT_ACTION_ACTION), NULL);
-
-  return self->name;
-}
-
-/*** GTK_SHORTCUT_ACTION_GACTION ***/
-
-typedef struct _GtkGActionAction GtkGActionAction;
-
-struct _GtkGActionAction
-{
-  GtkShortcutAction action;
-
-  GAction *gaction;
-};
-
-static void
-gtk_gaction_action_finalize (GtkShortcutAction *action)
-{
-  GtkGActionAction *self = (GtkGActionAction *) action;
-
-  g_object_unref (self->gaction);
-}
-
-static gboolean
-gtk_gaction_action_activate (GtkShortcutAction      *action,
-                             GtkShortcutActionFlags  flags,
-                             GtkWidget              *widget,
-                             GVariant               *args)
-{
-  GtkGActionAction *self = (GtkGActionAction *) action;
-
-  if (!gtk_shortcut_trigger_check_parameter_type (args, g_action_get_parameter_type (self->gaction)))
-    return FALSE;
-
-  if (!g_action_get_enabled (self->gaction))
-    return FALSE;
-
-  g_action_activate (self->gaction, args);
-
-  return TRUE;
-}
-
-static void
-gtk_gaction_action_print (GtkShortcutAction *action,
-                          GString           *string)
-{
-  GtkGActionAction *self = (GtkGActionAction *) action;
-
-  g_string_append_printf (string, "gaction(%s %p)", g_action_get_name (self->gaction), self->gaction);
-}
-
-static const GtkShortcutActionClass GTK_GACTION_ACTION_CLASS = {
-  GTK_SHORTCUT_ACTION_GACTION,
-  sizeof (GtkGActionAction),
-  "GtkGActionAction",
-  gtk_gaction_action_finalize,
-  gtk_gaction_action_activate,
-  gtk_gaction_action_print
-};
-
-/**
- * gtk_gaction_action_new:
- * @action: a #GAction
- *
- * Creates a new action that will activate the given @gaction when activated
- * with the passed in arguments.
- *
- * Returns: a new #GtkShortcutAction
- **/
-GtkShortcutAction *
-gtk_gaction_action_new (GAction *action)
-{
-  GtkGActionAction *self;
-
-  g_return_val_if_fail (G_IS_ACTION (action), NULL);
-
-  self = (GtkGActionAction *) gtk_shortcut_action_new (&GTK_GACTION_ACTION_CLASS);
-
-  self->gaction = g_object_ref (action);
-
-  return &self->action;
-}
-
-/**
- * gtk_gaction_action_get_gaction:
- * @action: a gaction action
- *
- * Queries the #GAction that will be activated when this action is activated.
- *
- * Returns: (transfer none): The #GAction that will be activated
- **/
-GAction *
-gtk_gaction_action_get_gaction (GtkShortcutAction *action)
-{
-  GtkGActionAction *self = (GtkGActionAction *) action;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION_TYPE (action, GTK_SHORTCUT_ACTION_GACTION), NULL);
-
-  return self->gaction;
-}
-
diff --git a/gtk/gtkshortcutaction.h b/gtk/gtkshortcutaction.h
deleted file mode 100644 (file)
index 95904fb..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_ACTION_H__
-#define __GTK_SHORTCUT_ACTION_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_ACTION (gtk_shortcut_action_get_type ())
-
-#define GTK_IS_SHORTCUT_ACTION(obj) ((obj) != NULL)
-
-/**
- * GtkShortcutFunc:
- * @widget: The widget passed to the activation
- * @args: The arguments passed to the activation
- * @user_data: The user data provided when activating the action
- *
- * Prototype for shortcuts based on user callbacks.
- */
-typedef gboolean (* GtkShortcutFunc) (GtkWidget *widget,
-                                      GVariant  *args,
-                                      gpointer   user_data);
-
-/**
- * GtkShortcutActionFlags:
- * @GTK_SHORTCUT_ACTION_EXCLUSIVE: The action is the only
- *     action that can be activated. If this flag is not set,
- *     a future activation may select a different action.
- *
- * List of flags that can be passed to action activation.
- * More flags may be added in the future.
- **/
-typedef enum {
-  GTK_SHORTCUT_ACTION_EXCLUSIVE = 1 << 0
-} GtkShortcutActionFlags;
-
-/**
- * GtkShortcutActionType:
- * @GTK_SHORTCUT_ACTION_NOTHING: Don't ever activate
- * @GTK_SHORTCUT_ACTION_CALLBACK: Call a custom user-provided callback
- * @GTK_SHORTCUT_ACTION_ACTIVATE: Call gtk_widget_activate() on the widget
- * @GTK_SHORTCUT_ACTION_MNEMONIC: Call gtk_widget_mnemonic_activate()
- *     on the widget
- * @GTK_SHORTCUT_ACTION_SIGNAL: Emit the given action signal on the widget
- * @GTK_SHORTCUT_ACTION_ACTION: Call the provided action on the widget
- * @GTK_SHORTCUT_ACTION_GACTION: Activate a GAction
- *
- * The type of a action determines what the action does when activated.
- **/
-typedef enum {
- GTK_SHORTCUT_ACTION_NOTHING,
- GTK_SHORTCUT_ACTION_CALLBACK,
- GTK_SHORTCUT_ACTION_ACTIVATE,
- GTK_SHORTCUT_ACTION_MNEMONIC,
- GTK_SHORTCUT_ACTION_SIGNAL,
- GTK_SHORTCUT_ACTION_ACTION,
- GTK_SHORTCUT_ACTION_GACTION
-} GtkShortcutActionType;
-
-GDK_AVAILABLE_IN_ALL
-GType                   gtk_shortcut_action_get_type            (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_shortcut_action_ref                 (GtkShortcutAction      *self);
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_action_unref               (GtkShortcutAction      *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutActionType   gtk_shortcut_action_get_action_type     (GtkShortcutAction      *self);
-
-GDK_AVAILABLE_IN_ALL
-char *                  gtk_shortcut_action_to_string           (GtkShortcutAction      *self);
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_action_print               (GtkShortcutAction      *self,
-                                                                 GString                *string);
-GDK_AVAILABLE_IN_ALL
-gboolean                gtk_shortcut_action_activate            (GtkShortcutAction      *self,
-                                                                 GtkShortcutActionFlags  flags,
-                                                                 GtkWidget              *widget,
-                                                                 GVariant               *args);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_nothing_action_new                  (void);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_callback_action_new                 (GtkShortcutFunc         callback,
-                                                                 gpointer                data,
-                                                                 GDestroyNotify          destroy);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_mnemonic_action_new                 (void);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_activate_action_new                 (void);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_signal_action_new                   (const char             *signal_name);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_signal_action_get_signal_name       (GtkShortcutAction      *action);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_action_action_new                   (const char             *name);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_action_action_get_name              (GtkShortcutAction      *action);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *     gtk_gaction_action_new                  (GAction                *action);
-GDK_AVAILABLE_IN_ALL
-GAction *               gtk_gaction_action_get_gaction          (GtkShortcutAction      *action);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_ACTION_H__ */
diff --git a/gtk/gtkshortcutactionprivate.h b/gtk/gtkshortcutactionprivate.h
deleted file mode 100644 (file)
index 4c5a0db..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_ACTION_PRIVATE_H__
-#define __GTK_SHORTCUT_ACTION_PRIVATE_H__
-
-#include "gtkshortcutaction.h"
-
-GtkShortcutAction *     gtk_shortcut_action_parse_builder       (GtkBuilder              *builder,
-                                                                 const char              *string,
-                                                                 GError                 **error);
-
-#endif /* __GTK_SHORTCUT_ACTION_PRIVATE_H__ */
diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c
deleted file mode 100644 (file)
index 0c2d1ba..0000000
+++ /dev/null
@@ -1,673 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/**
- * SECTION:gtkshortcutcontroller
- * @Short_description: Event controller for shortcuts
- * @Title: GtkShortcutController
- * @See_also: #GtkEventController, #GtkShortcut
- *
- * #GtkShortcutController is an event controller that manages shortcuts.
- *
- * #GtkShortcutController implements #GListModel for querying the shortcuts that
- * have been added to it.
- **/
-
-#include "config.h"
-
-#include "gtkshortcutcontrollerprivate.h"
-
-#include "gtkbuildable.h"
-#include "gtkconcatmodelprivate.h"
-#include "gtkeventcontrollerprivate.h"
-#include "gtkintl.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutmanager.h"
-#include "gtkshortcuttrigger.h"
-#include "gtktypebuiltins.h"
-#include "gtkwidgetprivate.h"
-
-#include <gdk/gdk.h>
-
-struct _GtkShortcutController
-{
-  GtkEventController parent_instance;
-
-  GListModel *shortcuts;
-  GtkShortcutScope scope;
-  GdkModifierType mnemonics_modifiers;
-
-  guint custom_shortcuts : 1;
-};
-
-struct _GtkShortcutControllerClass
-{
-  GtkEventControllerClass parent_class;
-};
-
-enum {
-  PROP_0,
-  PROP_MNEMONICS_MODIFIERS,
-  PROP_MODEL,
-  PROP_SCOPE,
-
-  N_PROPS
-};
-
-static GParamSpec *properties[N_PROPS] = { NULL, };
-
-static GType
-gtk_shortcut_controller_list_model_get_item_type (GListModel *list)
-{
-  return GTK_TYPE_SHORTCUT;
-}
-
-static guint
-gtk_shortcut_controller_list_model_get_n_items (GListModel *list)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (list);
-
-  return g_list_model_get_n_items (self->shortcuts);
-}
-
-static gpointer
-gtk_shortcut_controller_list_model_get_item (GListModel *list,
-                                             guint       position)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (list);
-
-  return g_list_model_get_item (self->shortcuts, position);
-}
-
-static void
-gtk_shortcut_controller_list_model_init (GListModelInterface *iface)
-{
-  iface->get_item_type = gtk_shortcut_controller_list_model_get_item_type;
-  iface->get_n_items = gtk_shortcut_controller_list_model_get_n_items;
-  iface->get_item = gtk_shortcut_controller_list_model_get_item;
-}
-
-static void
-gtk_shortcut_controller_buildable_add_child (GtkBuildable  *buildable,
-                                             GtkBuilder    *builder,
-                                             GObject       *child,
-                                             const gchar   *type)
-{
-  if (type != NULL)
-    {
-      GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
-    }
-  if (GTK_IS_SHORTCUT (child))
-    {
-      gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (buildable), GTK_SHORTCUT (child));
-    }
-  else
-    {
-      g_warning ("Cannot add an object of type %s to a controller of type %s",
-                 g_type_name (G_OBJECT_TYPE (child)), g_type_name (G_OBJECT_TYPE (buildable)));
-    }
-}
-
-static void
-gtk_shortcut_controller_buildable_init (GtkBuildableIface *iface)
-{
-  iface->add_child = gtk_shortcut_controller_buildable_add_child;
-}
-
-G_DEFINE_TYPE_WITH_CODE (GtkShortcutController, gtk_shortcut_controller,
-                         GTK_TYPE_EVENT_CONTROLLER,
-                         G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_shortcut_controller_list_model_init)
-                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_shortcut_controller_buildable_init))
-
-static gboolean
-gtk_shortcut_controller_is_rooted (GtkShortcutController *self)
-{
-  GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
-
-  if (widget == NULL)
-    return FALSE;
-
-  return gtk_widget_get_root (widget) != NULL;
-}
-
-static void
-gtk_shortcut_controller_set_property (GObject      *object,
-                                      guint         prop_id,
-                                      const GValue *value,
-                                      GParamSpec   *pspec)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
-  switch (prop_id)
-    {
-    case PROP_MNEMONICS_MODIFIERS:
-      gtk_shortcut_controller_set_mnemonics_modifiers (self, g_value_get_flags (value));
-      break;
-
-    case PROP_MODEL:
-      {
-        GListModel *model = g_value_get_object (value);
-        if (model && g_list_model_get_item_type (model) != GTK_TYPE_SHORTCUT)
-          {
-            g_warning ("Setting a model with type '%s' on a shortcut controller that requires 'GtkShortcut'",
-                       g_type_name (g_list_model_get_item_type (model)));
-            model = NULL;
-          }
-        if (model == NULL)
-          {
-            self->shortcuts = G_LIST_MODEL (g_list_store_new (GTK_TYPE_SHORTCUT));
-            self->custom_shortcuts = TRUE;
-          }
-        else
-          {
-            self->shortcuts = g_object_ref (model);
-            self->custom_shortcuts = FALSE;
-          }
-        g_signal_connect_swapped (self->shortcuts, "items-changed", G_CALLBACK (g_list_model_items_changed), self);
-      }
-      break;
-
-    case PROP_SCOPE:
-      gtk_shortcut_controller_set_scope (self, g_value_get_enum (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
-}
-
-static void
-gtk_shortcut_controller_get_property (GObject    *object,
-                                      guint       prop_id,
-                                      GValue     *value,
-                                      GParamSpec *pspec)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
-  switch (prop_id)
-    {
-    case PROP_MNEMONICS_MODIFIERS:
-      g_value_set_flags (value, self->mnemonics_modifiers);
-      break;
-
-    case PROP_SCOPE:
-      g_value_set_enum (value, self->scope);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
-}
-
-static void
-gtk_shortcut_controller_dispose (GObject *object)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
-  if (self->custom_shortcuts)
-    g_list_store_remove_all (G_LIST_STORE (self->shortcuts));
-
-  G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->dispose (object);
-}
-
-static void
-gtk_shortcut_controller_finalize (GObject *object)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
-  g_signal_handlers_disconnect_by_func (self->shortcuts, g_list_model_items_changed, self);
-  g_clear_object (&self->shortcuts);
-
-  G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->finalize (object);
-}
-
-static gboolean
-gtk_shortcut_controller_trigger_shortcut (GtkShortcutController *self,
-                                          GtkShortcut           *shortcut,
-                                          guint                  position,
-                                          GdkEvent              *event,
-                                          gboolean               enable_mnemonics)
-{
-  GtkWidget *widget;
-
-  if (!gtk_shortcut_trigger_trigger (gtk_shortcut_get_trigger (shortcut), event, enable_mnemonics))
-    return FALSE;
-
-  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
-  if (!self->custom_shortcuts &&
-      GTK_IS_CONCAT_MODEL (self->shortcuts))
-    {
-      GListModel *model = gtk_concat_model_get_model_for_item (GTK_CONCAT_MODEL (self->shortcuts), position);
-      if (GTK_IS_SHORTCUT_CONTROLLER (model))
-        widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (model));
-    }
-
-  return gtk_shortcut_action_activate (gtk_shortcut_get_action (shortcut),
-                                       GTK_SHORTCUT_ACTION_EXCLUSIVE, /* FIXME */
-                                       widget,
-                                       gtk_shortcut_get_arguments (shortcut));
-}
-
-static gboolean
-gtk_shortcut_controller_run_controllers (GtkEventController *controller,
-                                         GdkEvent           *event,
-                                         double              x,
-                                         double              y,
-                                         gboolean            enable_mnemonics)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
-  guint i;
-
-  for (i = 0; i < g_list_model_get_n_items (self->shortcuts); i++)
-    {
-      if (gtk_shortcut_controller_trigger_shortcut (self, 
-                                                    g_list_model_get_item (self->shortcuts, i),
-                                                    i,
-                                                    event,
-                                                    enable_mnemonics))
-        return TRUE;
-    }
-
-  return FALSE;
-}
-
-static gboolean
-gtk_shortcut_controller_handle_event (GtkEventController *controller,
-                                      GdkEvent           *event,
-                                      double              x,
-                                      double              y)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
-  gboolean enable_mnemonics;
-
-  if (self->scope != GTK_SHORTCUT_SCOPE_LOCAL)
-    return FALSE;
-
-  if (gdk_event_get_event_type (event) == GDK_KEY_PRESS)
-    {
-      GdkModifierType modifiers;
-      modifiers = gdk_event_get_modifier_state (event);
-      enable_mnemonics = (modifiers & gtk_accelerator_get_default_mod_mask ()) == self->mnemonics_modifiers;
-    }
-  else
-    {
-      enable_mnemonics = FALSE;
-    }
-
-  return gtk_shortcut_controller_run_controllers (controller, event, x, y, enable_mnemonics);
-}
-
-static void
-gtk_shortcut_controller_set_widget (GtkEventController *controller,
-                                    GtkWidget          *widget)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
-
-  GTK_EVENT_CONTROLLER_CLASS (gtk_shortcut_controller_parent_class)->set_widget (controller, widget);
-
-  if (_gtk_widget_get_root (widget))
-    gtk_shortcut_controller_root (self);
-}
-
-static void
-gtk_shortcut_controller_unset_widget (GtkEventController *controller)
-{
-  GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
-  GtkWidget *widget = gtk_event_controller_get_widget (controller);
-
-  if (_gtk_widget_get_root (widget))
-    gtk_shortcut_controller_unroot (self);
-
-  GTK_EVENT_CONTROLLER_CLASS (gtk_shortcut_controller_parent_class)->unset_widget (controller);
-}
-
-static void
-gtk_shortcut_controller_class_init (GtkShortcutControllerClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
-
-  object_class->dispose = gtk_shortcut_controller_dispose;
-  object_class->finalize = gtk_shortcut_controller_finalize;
-  object_class->set_property = gtk_shortcut_controller_set_property;
-  object_class->get_property = gtk_shortcut_controller_get_property;
-
-  controller_class->handle_event = gtk_shortcut_controller_handle_event;
-  controller_class->set_widget = gtk_shortcut_controller_set_widget;
-  controller_class->unset_widget = gtk_shortcut_controller_unset_widget;
-
-  /**
-   * GtkShortcutController:mnemonic-modifiers:
-   *
-   * The modifiers that need to be pressed to allow mnemonics activation.
-   */
-  properties[PROP_MNEMONICS_MODIFIERS] =
-      g_param_spec_flags ("mnemonic-modifiers",
-                          P_("Mnemonic modifers"),
-                          P_("The modifiers to be pressed to allow mnemonics activation"),
-                          GDK_TYPE_MODIFIER_TYPE,
-                          GDK_MOD1_MASK,
-                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
-  /**
-   * GtkShortcutController:model:
-   *
-   * A list model to take shortcuts from
-   */
-  properties[PROP_MODEL] =
-      g_param_spec_object ("model",
-                           P_("Model"),
-                           P_("A list model to take shortcuts from"),
-                           G_TYPE_LIST_MODEL,
-                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
-  /**
-   * GtkShortcutController:scope:
-   *
-   * What scope the shortcuts will be handled in.
-   */
-  properties[PROP_SCOPE] =
-      g_param_spec_enum ("scope",
-                         P_("Scope"),
-                         P_("What scope the shortcuts will be handled in"),
-                         GTK_TYPE_SHORTCUT_SCOPE,
-                         GTK_SHORTCUT_SCOPE_LOCAL,
-                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
-  g_object_class_install_properties (object_class, N_PROPS, properties);
-}
-
-static void
-gtk_shortcut_controller_init (GtkShortcutController *self)
-{
-  self->mnemonics_modifiers = GDK_MOD1_MASK;
-}
-
-void
-gtk_shortcut_controller_root (GtkShortcutController *self)
-{
-  GtkShortcutManager *manager;
-
-  switch (self->scope)
-    {
-    case GTK_SHORTCUT_SCOPE_LOCAL:
-      return;
-
-    case GTK_SHORTCUT_SCOPE_MANAGED:
-      {
-        GtkWidget *widget;
-
-        for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
-             !GTK_IS_SHORTCUT_MANAGER (widget);
-             widget = _gtk_widget_get_parent (widget))
-          ;
-
-        if (!GTK_IS_SHORTCUT_MANAGER (widget))
-          return;
-
-        manager = GTK_SHORTCUT_MANAGER (widget);
-      }
-      break;
-
-    case GTK_SHORTCUT_SCOPE_GLOBAL:
-      {
-        GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
-
-        if (!GTK_IS_SHORTCUT_MANAGER (root))
-          return;
-
-        manager = GTK_SHORTCUT_MANAGER (root);
-      }
-      break;
-
-    default:
-      g_assert_not_reached ();
-      return;
-    }
-
-  GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->add_controller (manager, self);
-}
-
-void
-gtk_shortcut_controller_unroot (GtkShortcutController *self)
-{
-  GtkShortcutManager *manager;
-
-  switch (self->scope)
-    {
-    case GTK_SHORTCUT_SCOPE_LOCAL:
-      return;
-
-    case GTK_SHORTCUT_SCOPE_MANAGED:
-      {
-        GtkWidget *widget;
-
-        for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
-             !GTK_IS_SHORTCUT_MANAGER (widget);
-             widget = _gtk_widget_get_parent (widget))
-          ;
-
-        if (!GTK_IS_SHORTCUT_MANAGER (widget))
-          return;
-
-        manager = GTK_SHORTCUT_MANAGER (widget);
-      }
-      break;
-
-    case GTK_SHORTCUT_SCOPE_GLOBAL:
-      {
-        GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
-
-        if (!GTK_IS_SHORTCUT_MANAGER (root))
-          return;
-
-        manager = GTK_SHORTCUT_MANAGER (root);
-      }
-      break;
-
-    default:
-      g_assert_not_reached ();
-      return;
-    }
-
-  GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->remove_controller (manager, self);
-}
-
-GtkEventController *
-gtk_shortcut_controller_new (void)
-{
-  return g_object_new (GTK_TYPE_SHORTCUT_CONTROLLER,
-                       NULL);
-}
-
-GtkEventController *
-gtk_shortcut_controller_new_for_model (GListModel *model)
-{
-  g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
-  g_return_val_if_fail (g_list_model_get_item_type (model) == GTK_TYPE_SHORTCUT, NULL);
-
-  return g_object_new (GTK_TYPE_SHORTCUT_CONTROLLER,
-                       "model", model,
-                       NULL);
-}
-
-/**
- * gtk_shortcut_controller_add_shortcut:
- * @self: the controller
- * @shortcut: a #GtkShortcut
- *
- * Adds @shortcut to the list of shortcuts handled by @self.
- *
- * If this controller uses an external shortcut list, this function does
- * nothing.
- *
- * The shortcut is added to the list so that it is triggered before
- * all existing shortcuts.
- *
- * FIXME: What's supposed to happen if a shortcut gets added twice?
- **/
-void
-gtk_shortcut_controller_add_shortcut (GtkShortcutController *self,
-                                      GtkShortcut           *shortcut)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
-  g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
-
-  if (!self->custom_shortcuts)
-    return;
-
-  g_list_store_append (G_LIST_STORE (self->shortcuts), shortcut);
-}
-
-/**
- * gtk_shortcut_controller_remove_shortcut:
- * @self: the controller
- * @shortcut: a #GtkShortcut
- *
- * Removes @shortcut from the list of shortcuts handled by @self.
- *
- * If @shortcut had not been added to @controller or this controller
- * uses an external shortcut list, this function does nothing.
- **/
-void
-gtk_shortcut_controller_remove_shortcut (GtkShortcutController  *self,
-                                         GtkShortcut            *shortcut)
-{
-  guint i;
-
-  g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
-  g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
-
-  if (!self->custom_shortcuts)
-    return;
-
-  for (i = 0; i < g_list_model_get_n_items (self->shortcuts); i++)
-    {
-      GtkShortcut *item = g_list_model_get_item (self->shortcuts, i);
-
-      if (item == shortcut)
-        {
-          g_object_unref (item);
-          g_list_store_remove (G_LIST_STORE (self->shortcuts), i);
-          return;
-        }
-
-      g_object_unref (item);
-    }
-}
-
-/**
- * gtk_shortcut_controller_set_scope:
- * @self: a #GtkShortcutController
- * @scope: the new scope to use
- *
- * Sets the controller to have the given @scope.
- *
- * The scope allows shortcuts to be activated outside of the normal
- * event propagation. In particular, it allows installing global
- * keyboard shortcuts that can be activated even when a widget does
- * not have focus.
- **/
-void
-gtk_shortcut_controller_set_scope (GtkShortcutController *self,
-                                   GtkShortcutScope       scope)
-{
-  gboolean rooted;
-
-  g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
-
-  if (self->scope == scope)
-    return;
-
-  rooted = gtk_shortcut_controller_is_rooted (self);
-
-  if (rooted)
-    gtk_shortcut_controller_unroot (self);
-
-  self->scope = scope;
-
-  if (rooted)
-    gtk_shortcut_controller_root (self);
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SCOPE]);
-}
-
-/**
- * gtk_shortcut_controller_get_scope:
- * @self: a #GtkShortcutController
- *
- * Gets the scope for when this controller activates its shortcuts. See
- * gtk_shortcut_controller_set_scope() for details.
- *
- * Returns: the controller's scope
- **/
-GtkShortcutScope
-gtk_shortcut_controller_get_scope (GtkShortcutController *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self), GTK_SHORTCUT_SCOPE_LOCAL);
-
-  return self->scope;
-}
-
-/**
- * gtk_shortcut_controller_set_mnemonics_modifiers:
- * @self: a #GtkShortcutController
- * @modifiers: the new mnemonics_modifiers to use
- *
- * Sets the controller to have the given @mnemonics_modifiers.
- *
- * The mnemonics modifiers determines which modifiers need to be pressed to allow
- * activation of shortcuts with mnemonics triggers.
- *
- * This value is only relevant for local shortcut controllers. Global and managed
- * shortcut controllers will have their shortcuts activated from other places which
- * have their own modifiers for activating mnemonics.
- **/
-void
-gtk_shortcut_controller_set_mnemonics_modifiers (GtkShortcutController *self,
-                                                 GdkModifierType        modifiers)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
-
-  if (self->mnemonics_modifiers == modifiers)
-    return;
-
-  self->mnemonics_modifiers = modifiers;
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MNEMONICS_MODIFIERS]);
-}
-
-/**
- * gtk_shortcut_controller_get_mnemonics_modifiers:
- * @self: a #GtkShortcutController
- *
- * Gets the mnemonics modifiers for when this controller activates its shortcuts. See
- * gtk_shortcut_controller_set_mnemonics_modifiers() for details.
- *
- * Returns: the controller's mnemonics modifiers
- **/
-GdkModifierType
-gtk_shortcut_controller_get_mnemonics_modifiers (GtkShortcutController *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self), GTK_SHORTCUT_SCOPE_LOCAL);
-
-  return self->mnemonics_modifiers;
-}
-
diff --git a/gtk/gtkshortcutcontroller.h b/gtk/gtkshortcutcontroller.h
deleted file mode 100644 (file)
index aeb50e7..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_SHORTCUT_CONTROLLER_H__
-#define __GTK_SHORTCUT_CONTROLLER_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtkeventcontroller.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_CONTROLLER         (gtk_shortcut_controller_get_type ())
-#define GTK_SHORTCUT_CONTROLLER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_SHORTCUT_CONTROLLER, GtkShortcutController))
-#define GTK_SHORTCUT_CONTROLLER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_SHORTCUT_CONTROLLER, GtkShortcutControllerClass))
-#define GTK_IS_SHORTCUT_CONTROLLER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_SHORTCUT_CONTROLLER))
-#define GTK_IS_SHORTCUT_CONTROLLER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_SHORTCUT_CONTROLLER))
-#define GTK_SHORTCUT_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_SHORTCUT_CONTROLLER, GtkShortcutControllerClass))
-
-typedef struct _GtkShortcutController GtkShortcutController;
-typedef struct _GtkShortcutControllerClass GtkShortcutControllerClass;
-
-GDK_AVAILABLE_IN_ALL
-GType                   gtk_shortcut_controller_get_type                (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkEventController *    gtk_shortcut_controller_new                     (void);
-GDK_AVAILABLE_IN_ALL
-GtkEventController *    gtk_shortcut_controller_new_for_model           (GListModel             *list);
-
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_controller_set_mnemonics_modifiers (GtkShortcutController  *self,
-                                                                         GdkModifierType         modifiers);
-GDK_AVAILABLE_IN_ALL
-GdkModifierType         gtk_shortcut_controller_get_mnemonics_modifiers (GtkShortcutController  *self);
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_controller_set_scope               (GtkShortcutController  *self,
-                                                                         GtkShortcutScope        scope);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutScope        gtk_shortcut_controller_get_scope               (GtkShortcutController  *self);
-
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_controller_add_shortcut            (GtkShortcutController  *self,
-                                                                         GtkShortcut            *shortcut);
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_controller_remove_shortcut         (GtkShortcutController  *self,
-                                                                         GtkShortcut            *shortcut);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_CONTROLLER_H__ */
diff --git a/gtk/gtkshortcutcontrollerprivate.h b/gtk/gtkshortcutcontrollerprivate.h
deleted file mode 100644 (file)
index db1b52c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_CONTROLLER_PRIVATE_H__
-#define __GTK_SHORTCUT_CONTROLLER_PRIVATE_H__
-
-#include "gtkshortcutcontroller.h"
-
-void                    gtk_shortcut_controller_root                    (GtkShortcutController  *controller);
-void                    gtk_shortcut_controller_unroot                  (GtkShortcutController  *controller);
-
-#endif /* __GTK_SHORTCUT_CONTROLLER_H__ */
index 90471af3ee5b0bd1a7c81e092350243666249d38..704324fa8c40d7443400f9f8e4d4cee23de7d1ce 100644 (file)
@@ -303,7 +303,8 @@ parse_combination (GtkShortcutLabel *self,
   accels = g_strsplit (str, "&", 0);
   for (k = 0; accels[k]; k++)
     {
-      if (!gtk_accelerator_parse (accels[k], &key, &modifier))
+      gtk_accelerator_parse (accels[k], &key, &modifier);
+      if (key == 0 && modifier == 0)
         {
           retval = FALSE;
           break;
diff --git a/gtk/gtkshortcutmanager.c b/gtk/gtkshortcutmanager.c
deleted file mode 100644 (file)
index 64fdd7b..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#include "config.h"
-
-#include "gtkshortcutmanager.h"
-#include "gtkshortcutmanagerprivate.h"
-#include "gtkconcatmodelprivate.h"
-
-/**
- * SECTION:gtkshortcutmanager
- * @title: GtkShortcutManager
- * @short_description: Interface for managing shortcuts
- *
- * The GtkShortcutManager interface is used to implement
- * shortcut scopes.
- */
-
-G_DEFINE_INTERFACE (GtkShortcutManager, gtk_shortcut_manager, G_TYPE_OBJECT)
-
-void
-gtk_shortcut_manager_create_controllers (GtkWidget *widget)
-{
-  GtkConcatModel *model;
-  GtkEventController *controller;
-
-  model = gtk_concat_model_new (GTK_TYPE_SHORTCUT);
-  g_object_set_data_full (G_OBJECT (widget), "gtk-shortcut-manager-bubble", model, g_object_unref);
-  controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (model));
-  gtk_event_controller_set_name (controller, "gtk-shortcut-manager-bubble");
-  gtk_widget_add_controller (widget, controller);
-
-  model = gtk_concat_model_new (GTK_TYPE_SHORTCUT);
-  g_object_set_data_full (G_OBJECT (widget), "gtk-shortcut-manager-capture", model, g_object_unref);
-  controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (model));
-  gtk_event_controller_set_name (controller, "gtk-shortcut-manager-capture");
-  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
-  gtk_widget_add_controller (widget, controller);
-}
-
-static GtkConcatModel *
-gtk_shortcut_manager_get_model (GtkShortcutManager  *self,
-                                GtkPropagationPhase  phase)
-{
-  switch (phase)
-    {
-    case GTK_PHASE_CAPTURE:
-      return g_object_get_data (G_OBJECT (self), "gtk-shortcut-manager-capture");
-    case GTK_PHASE_BUBBLE:
-      return g_object_get_data (G_OBJECT (self), "gtk-shortcut-manager-bubble");
-    case GTK_PHASE_NONE:
-    case GTK_PHASE_TARGET:
-      return NULL;
-    default:
-      g_assert_not_reached ();
-      return NULL;
-    }
-}
-
-static void
-gtk_shortcut_manager_default_add_controller (GtkShortcutManager    *self,
-                                             GtkShortcutController *controller)
-{
-  GtkConcatModel *model;
-
-  model = gtk_shortcut_manager_get_model (self, 
-                                          gtk_event_controller_get_propagation_phase (GTK_EVENT_CONTROLLER (controller)));
-  if (model)
-    gtk_concat_model_append (model, G_LIST_MODEL (controller));
-}
-
-static void
-gtk_shortcut_manager_default_remove_controller (GtkShortcutManager    *self,
-                                                GtkShortcutController *controller)
-{
-  GtkConcatModel *model;
-
-  model = gtk_shortcut_manager_get_model (self, 
-                                          gtk_event_controller_get_propagation_phase (GTK_EVENT_CONTROLLER (controller)));
-  if (model)
-    gtk_concat_model_remove (model, G_LIST_MODEL (controller));
-}
-
-static void
-gtk_shortcut_manager_default_init (GtkShortcutManagerInterface *iface)
-{
-  iface->add_controller = gtk_shortcut_manager_default_add_controller;
-  iface->remove_controller = gtk_shortcut_manager_default_remove_controller;
-}
-
diff --git a/gtk/gtkshortcutmanager.h b/gtk/gtkshortcutmanager.h
deleted file mode 100644 (file)
index 0d4ece9..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_MANAGER_H__
-#define __GTK_SHORTCUT_MANAGER_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtkshortcutcontroller.h>
-#include <gtk/gtkwidget.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_MANAGER               (gtk_shortcut_manager_get_type ())
-
-GDK_AVAILABLE_IN_ALL
-G_DECLARE_INTERFACE (GtkShortcutManager, gtk_shortcut_manager, GTK, SHORTCUT_MANAGER, GtkWidget)
-
-/**
- * GtkShortcutManager:
- *
- * This object is used to implement support for #GtkShortcutScopes. Every
- * widget that implements #GtkShortcutManager will be used as a
- * %GTK_SHORTCUT_SCOPE_MANAGED.
- */
-
-/**
- * GtkShortcutManagerInterface:
- * @add_controller: Add a #GtkShortcutController to be managed.
- * @remove_controller: Remove a #GtkShortcutController that had previously
- *     been added.
- *
- * The list of functions that can be implemented for the #GtkShortcutManager interface.
- *
- * Note that no function is mandatory to implement, the default implementation will work
- * fine.
- */
-struct _GtkShortcutManagerInterface
-{
-  /*< private >*/
-  GTypeInterface g_iface;
-
-  /*< public >*/
-  void                  (* add_controller)              (GtkShortcutManager           *self,
-                                                         GtkShortcutController        *controller);
-  void                  (* remove_controller)           (GtkShortcutManager           *self,
-                                                         GtkShortcutController        *controller);
-};
-
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_MANAGER_H__ */
diff --git a/gtk/gtkshortcutmanagerprivate.h b/gtk/gtkshortcutmanagerprivate.h
deleted file mode 100644 (file)
index 72424db..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __GTK_SHORTCUT_MANAGER_PRIVATE_H__
-#define __GTK_SHORTCUT_MANAGER__PRIVATE_H__
-
-#include "gtkshortcutmanager.h"
-
-G_BEGIN_DECLS
-
-void gtk_shortcut_manager_create_controllers (GtkWidget *widget);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_MANAGER_PRIVATE_H__ */
index 337ece2539aca2221c76e65c23c3fae29c2091b1..6a95e348a1329581dec03640aaaa8d21cffefd34 100644 (file)
@@ -30,6 +30,7 @@
 #include "gtkorientable.h"
 #include "gtksizegroup.h"
 #include "gtkwidget.h"
+#include "gtkbindings.h"
 #include "gtkprivate.h"
 #include "gtkmarshalers.h"
 #include "gtkgesturepan.h"
@@ -306,6 +307,7 @@ gtk_shortcuts_section_class_init (GtkShortcutsSectionClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   object_class->finalize = gtk_shortcuts_section_finalize;
   object_class->get_property = gtk_shortcuts_section_get_property;
@@ -386,23 +388,23 @@ gtk_shortcuts_section_class_init (GtkShortcutsSectionClass *klass)
                   G_TYPE_BOOLEAN, 1,
                   G_TYPE_INT);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Up, 0,
-                                       "change-current-page",
-                                       "(i)", -1);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Down, 0,
-                                       "change-current-page",
-                                       "(i)", 1);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Up, GDK_CONTROL_MASK,
-                                       "change-current-page",
-                                       "(i)", -1);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Page_Down, GDK_CONTROL_MASK,
-                                       "change-current-page",
-                                       "(i)", 1);
-
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Up, 0,
+                                "change-current-page", 1,
+                                G_TYPE_INT, -1);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Down, 0,
+                                "change-current-page", 1,
+                                G_TYPE_INT, 1);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Up, GDK_CONTROL_MASK,
+                                "change-current-page", 1,
+                                G_TYPE_INT, -1);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_KEY_Page_Down, GDK_CONTROL_MASK,
+                                "change-current-page", 1,
+                                G_TYPE_INT, 1);
   gtk_widget_class_set_css_name (widget_class, I_("shortcuts-section"));
 }
 
index a2d580f0ebc2caa53a8980ea3e32acc213c923c3..292b1171bee38f05cca40155a52311ccdb2965a4 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "gtkshortcutswindowprivate.h"
 
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkgrid.h"
 #include "gtkheaderbar.h"
@@ -773,6 +774,7 @@ gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkBindingSet *binding_set = gtk_binding_set_by_class (klass);
 
   object_class->constructed = gtk_shortcuts_window_constructed;
   object_class->finalize = gtk_shortcuts_window_finalize;
@@ -854,14 +856,8 @@ gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
                                  G_TYPE_NONE,
                                  0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Escape, 0,
-                                       "close",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_f, GDK_CONTROL_MASK,
-                                       "search",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_f, GDK_CONTROL_MASK, "search", 0);
 
   g_type_ensure (GTK_TYPE_SHORTCUTS_GROUP);
   g_type_ensure (GTK_TYPE_SHORTCUTS_SHORTCUT);
diff --git a/gtk/gtkshortcuttrigger.c b/gtk/gtkshortcuttrigger.c
deleted file mode 100644 (file)
index dce75a1..0000000
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-/**
- * SECTION:gtkshortcuttrigger
- * @Title: GtkShortcutTrigger
- * @Short_description: Triggers to track if shortcuts should be activated
- * @See_also: #GtkShortcut
- *
- * #GtkShortcutTrigger is the object used to track if a #GtkShortcut should be
- * activated. For this purpose, gtk_shortcut_trigger_trigger() can be called
- * on a #GdkEvent.
- *
- * #GtkShortcutTriggers contain functions that allow easy presentation to end
- * users as well as being printed for debugging.
- *
- * All #GtkShortcutTriggers are immutable, you can only specify their properties
- * during construction. If you want to change a trigger, you have to replace it
- * with a new one.
- */
-
-#include "config.h"
-
-#include "gtkshortcuttrigger.h"
-
-#include "gtkaccelgroupprivate.h"
-
-typedef struct _GtkShortcutTriggerClass GtkShortcutTriggerClass;
-
-#define GTK_IS_SHORTCUT_TRIGGER_TYPE(trigger,type) (GTK_IS_SHORTCUT_TRIGGER (trigger) && (trigger)->trigger_class->trigger_type == (type))
-
-struct _GtkShortcutTrigger
-{
-  const GtkShortcutTriggerClass *trigger_class;
-
-  gatomicrefcount ref_count;
-};
-
-struct _GtkShortcutTriggerClass
-{
-  GtkShortcutTriggerType trigger_type;
-  gsize struct_size;
-  const char *type_name;
-
-  void            (* finalize)    (GtkShortcutTrigger  *trigger);
-  gboolean        (* trigger)     (GtkShortcutTrigger  *trigger,
-                                   GdkEvent            *event,
-                                   gboolean             enable_mnemonics);
-  guint           (* hash)        (GtkShortcutTrigger  *trigger);
-  int             (* compare)     (GtkShortcutTrigger  *trigger1,
-                                   GtkShortcutTrigger  *trigger2);
-  void            (* print)       (GtkShortcutTrigger  *trigger,
-                                   GString             *string);
-  gboolean        (* print_label) (GtkShortcutTrigger  *trigger,
-                                   GdkDisplay          *display,
-                                   GString             *string);
-};
-
-G_DEFINE_BOXED_TYPE (GtkShortcutTrigger, gtk_shortcut_trigger,
-                     gtk_shortcut_trigger_ref,
-                     gtk_shortcut_trigger_unref)
-
-static void
-gtk_shortcut_trigger_finalize (GtkShortcutTrigger *self)
-{
-  self->trigger_class->finalize (self);
-
-  g_free (self);
-}
-
-/*< private >
- * gtk_shortcut_trigger_new:
- * @trigger_class: class structure for this trigger
- *
- * Returns: (transfer full): the newly created #GtkShortcutTrigger
- */
-static GtkShortcutTrigger *
-gtk_shortcut_trigger_new (const GtkShortcutTriggerClass *trigger_class)
-{
-  GtkShortcutTrigger *self;
-
-  g_return_val_if_fail (trigger_class != NULL, NULL);
-
-  self = g_malloc0 (trigger_class->struct_size);
-  g_atomic_ref_count_init (&self->ref_count);
-
-  self->trigger_class = trigger_class;
-
-  return self;
-}
-
-/**
- * gtk_shortcut_trigger_ref:
- * @self: a #GtkShortcutTrigger
- *
- * Acquires a reference on the given #GtkShortcutTrigger.
- *
- * Returns: (transfer full): the #GtkShortcutTrigger with
- *    an additional reference
- */
-GtkShortcutTrigger *
-gtk_shortcut_trigger_ref (GtkShortcutTrigger *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), NULL);
-
-  g_atomic_ref_count_inc (&self->ref_count);
-
-  return self;
-}
-
-/**
- * gtk_shortcut_trigger_unref:
- * @self: (transfer full): a #GtkShortcutTrigger
- *
- * Releases a reference on the given #GtkShortcutTrigger.
- *
- * If the reference was the last, the resources associated
- * to the trigger are freed.
- */
-void
-gtk_shortcut_trigger_unref (GtkShortcutTrigger *self)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT_TRIGGER (self));
-
-  if (g_atomic_ref_count_dec (&self->ref_count))
-    gtk_shortcut_trigger_finalize (self);
-}
-
-/**
- * gtk_shortcut_trigger_get_trigger_type:
- * @self: a #GtkShortcutTrigger
- *
- * Returns the type of the @trigger.
- *
- * Returns: the type of the #GtkShortcutTrigger
- */
-GtkShortcutTriggerType
-gtk_shortcut_trigger_get_trigger_type (GtkShortcutTrigger *self)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), GTK_SHORTCUT_TRIGGER_NEVER);
-
-  return self->trigger_class->trigger_type;
-}
-
-/**
- * gtk_shortcut_trigger_trigger:
- * @self: a #GtkShortcutTrigger
- * @event: the event to check
- * @enable_mnemonics: %TRUE if mnemonics should trigger. Usually the
- *     value of this property is determined by checking that the passed
- *     in @event is a Key event and has the right modifiers set.
- *
- * Checks if the given @event triggers @self. If so,
- * returns %TRUE.
- *
- * Returns: %TRUE if this event triggered the trigger
- **/
-gboolean
-gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self,
-                              GdkEvent           *event,
-                              gboolean            enable_mnemonics)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), FALSE);
-
-  return self->trigger_class->trigger (self, event, enable_mnemonics);
-}
-
-/**
- * gtk_shortcut_trigger_parse_string:
- * @string: the string to parse
- *
- * Tries to parse the given string into a trigger. On success,
- * the parsed trigger is returned. When parsing failed, %NULL is
- * returned.
- *
- * FIXME: Document the supported format here once we've figured
- * it out.
- * For now, this function only supports gtk_accelerator_parse() and
- * can only return a trigger of type %GTK_SHORTCUT_TRIGGER_KEYVAL.
- *
- * Returns: a new #GtkShortcutTrigger or %NULL on error
- **/
-GtkShortcutTrigger *
-gtk_shortcut_trigger_parse_string (const char *string)
-{
-  GdkModifierType modifiers;
-  guint keyval;
-
-  g_return_val_if_fail (string != NULL, NULL);
-
-  if (gtk_accelerator_parse (string, &keyval, &modifiers))
-    return gtk_keyval_trigger_new (keyval, modifiers);
-
-  return NULL;
-}
-
-/**
- * gtk_shortcut_trigger_to_string:
- * @self: a #GtkShortcutTrigger
- *
- * Prints the given trigger into a human-readable string.
- * This is a small wrapper around gdk_content_formats_print()
- * to help when debugging.
- *
- * Returns: (transfer full): a new string
- **/
-char *
-gtk_shortcut_trigger_to_string (GtkShortcutTrigger *self)
-{
-  GString *string;
-
-  g_return_val_if_fail (self != NULL, NULL);
-
-  string = g_string_new (NULL);
-  gtk_shortcut_trigger_print (self, string);
-
-  return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_shortcut_trigger_print:
- * @self: a #GtkShortcutTrigger
- * @string: a #GString to print into
- *
- * Prints the given trigger into a string for the developer.
- * This is meant for debugging and logging.
- *
- * The form of the representation may change at any time
- * and is not guaranteed to stay identical.
- **/
-void
-gtk_shortcut_trigger_print (GtkShortcutTrigger *self,
-                            GString            *string)
-{
-  g_return_if_fail (GTK_IS_SHORTCUT_TRIGGER (self));
-  g_return_if_fail (string != NULL);
-
-  return self->trigger_class->print (self, string);
-}
-
-/**
- * gtk_shortcut_trigger_to_label:
- * @self: a #GtkShortcutTrigger
- * @display: #GdkDisplay to print for
- *
- * Gets textual representation for the given trigger. This
- * function is returning a translated string for presentation
- * to end users for example in menu items or in help texts.
- *
- * The @display in use may influence the resulting string in
- * various forms, such as resolving hardware keycodes or by
- * causing display-specific modifier names.
- *
- * The form of the representation may change at any time and is
- * not guaranteed to stay identical.
- *
- * Returns: (transfer full): a new string
- **/
-char *
-gtk_shortcut_trigger_to_label (GtkShortcutTrigger *self,
-                               GdkDisplay         *display)
-{
-  GString *string;
-
-  g_return_val_if_fail (self != NULL, NULL);
-
-  string = g_string_new (NULL);
-  gtk_shortcut_trigger_print_label (self, display, string);
-
-  return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_shortcut_trigger_print_label:
- * @self: a #GtkShortcutTrigger
- * @display: #GdkDisplay to print for
- * @string: a #GString to print into
- *
- * Prints the given trigger into a string. This function is
- * returning a translated string for presentation to end users
- * for example in menu items or in help texts.
- *
- * The @display in use may influence the resulting string in
- * various forms, such as resolving hardware keycodes or by
- * causing display-specific modifier names.
- *
- * The form of the representation may change at any time and is
- * not guaranteed to stay identical.
- *
- * Returns: %TRUE if something was printed or %FALSE if the
- *     trigger did not have a textual representation suitable
- *     for end users.
- **/
-gboolean
-gtk_shortcut_trigger_print_label (GtkShortcutTrigger *self,
-                                  GdkDisplay         *display,
-                                  GString            *string)
-{
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), FALSE);
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
-  g_return_val_if_fail (string != NULL, FALSE);
-
-  return self->trigger_class->print_label (self, display, string);
-}
-
-/**
- * gtk_shortcut_trigger_hash:
- * @trigger: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- *
- * Generates a hash value for a #GtkShortcutTrigger.
- *
- * The output of this function is guaranteed to be the same for a given
- * value only per-process.  It may change between different processor
- * architectures or even different versions of GTK.  Do not use this
- * function as a basis for building protocols or file formats.
- *
- * The types of @trigger is #gconstpointer only to allow use of this
- * function with #GHashTable. They must each be a #GtkShortcutTrigger.
- *
- * Returns: a hash value corresponding to @trigger
- **/
-guint
-gtk_shortcut_trigger_hash (gconstpointer trigger)
-{
-  GtkShortcutTrigger *t = (GtkShortcutTrigger *) trigger;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (trigger), 0);
-
-  return t->trigger_class->hash (t);
-}
-
-/**
- * gtk_shortcut_trigger_equal:
- * @trigger1: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- * @trigger2: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- *
- * Checks if @trigger1 and @trigger2 trigger under the same conditions.
- *
- * The types of @one and @two are #gconstpointer only to allow use of this
- * function with #GHashTable. They must each be a #GtkShortcutTrigger.
- *
- * Returns: %TRUE if @trigger1 and @trigger2 are equal
- **/
-gboolean
-gtk_shortcut_trigger_equal (gconstpointer trigger1,
-                            gconstpointer trigger2)
-{
-  return gtk_shortcut_trigger_compare (trigger1, trigger2) == 0;
-}
-
-/**
- * gtk_shortcut_trigger_compare:
- * @trigger1: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- * @trigger2: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- *
- * 
- * The types of @one and @two are #gconstpointer only to allow use of this
- * function as a #GCompareFunc. They must each be a #GtkShortcutTrigger.
- *
- * Returns: An integer less than, equal to, or greater than zero if
- *     @trigger1 is found, respectively, to be less than, to match,
- *     or be greater than @trigger2.
- **/
-gint
-gtk_shortcut_trigger_compare (gconstpointer trigger1,
-                              gconstpointer trigger2)
-{
-  GtkShortcutTrigger *t1 = (GtkShortcutTrigger *) trigger1;
-  GtkShortcutTrigger *t2 = (GtkShortcutTrigger *) trigger2;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (trigger1), -1);
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (trigger2), 1);
-
-  if (t1->trigger_class != t2->trigger_class)
-    return t1->trigger_class->trigger_type - t2->trigger_class->trigger_type;
-
-  return t1->trigger_class->compare (t1, t2);
-}
-
-/*** GTK_SHORTCUT_TRIGGER_NEVER ***/
-
-typedef struct _GtkNeverTrigger GtkNeverTrigger;
-
-struct _GtkNeverTrigger
-{
-  GtkShortcutTrigger trigger;
-
-  guint never;
-  GdkModifierType modifiers;
-};
-
-static void
-gtk_never_trigger_finalize (GtkShortcutTrigger *trigger)
-{
-  g_assert_not_reached ();
-}
-
-static gboolean
-gtk_never_trigger_trigger (GtkShortcutTrigger *trigger,
-                           GdkEvent           *event,
-                           gboolean            enable_mnemonics)
-{
-  return FALSE;
-}
-
-static guint
-gtk_never_trigger_hash (GtkShortcutTrigger *trigger)
-{
-  return GTK_SHORTCUT_TRIGGER_NEVER;
-}
-
-static int
-gtk_never_trigger_compare (GtkShortcutTrigger  *trigger1,
-                           GtkShortcutTrigger  *trigger2)
-{
-  return 0;
-}
-
-static void
-gtk_never_trigger_print (GtkShortcutTrigger *trigger,
-                         GString            *string)
-                  
-{
-  g_string_append (string, "<never>");
-}
-
-static gboolean
-gtk_never_trigger_print_label (GtkShortcutTrigger *trigger,
-                               GdkDisplay         *display,
-                               GString            *string)
-{
-  return FALSE;
-}
-
-static const GtkShortcutTriggerClass GTK_NEVER_TRIGGER_CLASS = {
-  GTK_SHORTCUT_TRIGGER_NEVER,
-  sizeof (GtkNeverTrigger),
-  "GtkNeverTrigger",
-  gtk_never_trigger_finalize,
-  gtk_never_trigger_trigger,
-  gtk_never_trigger_hash,
-  gtk_never_trigger_compare,
-  gtk_never_trigger_print,
-  gtk_never_trigger_print_label
-};
-
-static GtkNeverTrigger never = { { &GTK_NEVER_TRIGGER_CLASS, 1 } };
-
-/**
- * gtk_never_trigger_get:
- *
- * Gets the never trigger. This is a singleton for a trigger
- * that never triggers. Use this trigger instead of %NULL
- * because it implements all virtual functions.
- *
- * Returns: (transfer none): The never trigger
- */
-GtkShortcutTrigger *
-gtk_never_trigger_get (void)
-{
-  return &never.trigger;
-}
-
-/*** GTK_KEYVAL_TRIGGER ***/
-
-typedef struct _GtkKeyvalTrigger GtkKeyvalTrigger;
-
-struct _GtkKeyvalTrigger
-{
-  GtkShortcutTrigger trigger;
-
-  guint keyval;
-  GdkModifierType modifiers;
-};
-
-static void
-gtk_keyval_trigger_finalize (GtkShortcutTrigger *trigger)
-{
-}
-
-static gboolean
-gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger,
-                            GdkEvent           *event,
-                            gboolean            enable_mnemonics)
-{
-  GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
-  GdkModifierType modifiers;
-  guint keyval;
-
-  if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
-    return FALSE;
-
-  /* XXX: This needs to deal with groups */
-  modifiers = gdk_event_get_modifier_state (event);
-  keyval = gdk_key_event_get_keyval (event);
-
-  if (keyval == GDK_KEY_ISO_Left_Tab)
-    keyval = GDK_KEY_Tab;
-  else
-    keyval = gdk_keyval_to_lower (keyval);
-
-  return keyval == self->keyval && modifiers == self->modifiers;
-}
-
-static guint
-gtk_keyval_trigger_hash (GtkShortcutTrigger *trigger)
-{
-  GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
-
-  return (self->modifiers << 24)
-       | (self->modifiers >> 8)
-       | (self->keyval << 16)
-       | GTK_SHORTCUT_TRIGGER_KEYVAL;
-}
-
-static int
-gtk_keyval_trigger_compare (GtkShortcutTrigger  *trigger1,
-                            GtkShortcutTrigger  *trigger2)
-{
-  GtkKeyvalTrigger *self1 = (GtkKeyvalTrigger *) trigger1;
-  GtkKeyvalTrigger *self2 = (GtkKeyvalTrigger *) trigger2;
-
-  if (self1->modifiers != self2->modifiers)
-    return self2->modifiers - self1->modifiers;
-
-  return self1->keyval - self2->keyval;
-}
-
-static void
-gtk_keyval_trigger_print (GtkShortcutTrigger *trigger,
-                          GString            *string)
-                  
-{
-  GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
-  char *accelerator_name;
-
-  accelerator_name = gtk_accelerator_name (self->keyval, self->modifiers);
-  g_string_append (string, accelerator_name);
-  g_free (accelerator_name);
-}
-
-static gboolean
-gtk_keyval_trigger_print_label (GtkShortcutTrigger *trigger,
-                                GdkDisplay         *display,
-                                GString            *string)
-{
-  GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
-
-  gtk_accelerator_print_label (string, self->keyval, self->modifiers);
-
-  return TRUE;
-}
-
-static const GtkShortcutTriggerClass GTK_KEYVAL_TRIGGER_CLASS = {
-  GTK_SHORTCUT_TRIGGER_KEYVAL,
-  sizeof (GtkKeyvalTrigger),
-  "GtkKeyvalTrigger",
-  gtk_keyval_trigger_finalize,
-  gtk_keyval_trigger_trigger,
-  gtk_keyval_trigger_hash,
-  gtk_keyval_trigger_compare,
-  gtk_keyval_trigger_print,
-  gtk_keyval_trigger_print_label
-};
-
-/**
- * gtk_keyval_trigger_new:
- * @keyval: The keyval to trigger for
- * @modifiers: the modifiers that need to be present
- *
- * Creates a #GtkShortcutTrigger that will trigger whenever
- * the key with the given @keyval and @modifiers is pressed.
- *
- * Returns: A new #GtkShortcutTrigger
- */
-GtkShortcutTrigger *
-gtk_keyval_trigger_new (guint           keyval,
-                        GdkModifierType modifiers)
-{
-  GtkKeyvalTrigger *self;
-
-  self = (GtkKeyvalTrigger *) gtk_shortcut_trigger_new (&GTK_KEYVAL_TRIGGER_CLASS);
-
-  /* We store keyvals as lower key */
-  if (keyval == GDK_KEY_ISO_Left_Tab)
-    self->keyval = GDK_KEY_Tab;
-  else
-    self->keyval = gdk_keyval_to_lower (keyval);
-  self->modifiers = modifiers;
-
-  return &self->trigger;
-}
-
-/**
- * gtk_keyval_trigger_get_modifiers:
- * @self: a keyval #GtkShortcutTrigger
- *
- * Gets the modifiers that must be present to succeed
- * triggering @self.
- *
- * Returns: the modifiers
- **/
-GdkModifierType
-gtk_keyval_trigger_get_modifiers (GtkShortcutTrigger *self)
-{
-  GtkKeyvalTrigger *trigger = (GtkKeyvalTrigger *) self;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_KEYVAL), 0);
-
-  return trigger->modifiers;
-}
-
-/**
- * gtk_keyval_trigger_get_keyval:
- * @self: a keyval #GtkShortcutTrigger
- *
- * Gets the keyval that must be pressed to succeed
- * triggering @self.
- *
- * Returns: the keyval
- **/
-guint
-gtk_keyval_trigger_get_keyval (GtkShortcutTrigger *self)
-{
-  GtkKeyvalTrigger *trigger = (GtkKeyvalTrigger *) self;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_KEYVAL), 0);
-
-  return trigger->keyval;
-}
-
-/*** GTK_MNEMONIC_TRIGGER ***/
-
-typedef struct _GtkMnemonicTrigger GtkMnemonicTrigger;
-
-struct _GtkMnemonicTrigger
-{
-  GtkShortcutTrigger trigger;
-
-  guint keyval;
-};
-
-static void
-gtk_mnemonic_trigger_finalize (GtkShortcutTrigger *trigger)
-{
-}
-
-static gboolean
-gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger,
-                              GdkEvent           *event,
-                              gboolean            enable_mnemonics)
-{
-  GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-  guint keyval;
-
-  if (!enable_mnemonics)
-    return FALSE;
-
-  if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
-    return FALSE;
-
-  /* XXX: This needs to deal with groups */
-  keyval = gdk_key_event_get_keyval (event);
-
-  if (keyval == GDK_KEY_ISO_Left_Tab)
-    keyval = GDK_KEY_Tab;
-  else
-    keyval = gdk_keyval_to_lower (keyval);
-
-  return keyval == self->keyval;
-}
-
-static guint
-gtk_mnemonic_trigger_hash (GtkShortcutTrigger *trigger)
-{
-  GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-
-  return (self->keyval << 8)
-       | GTK_SHORTCUT_TRIGGER_MNEMONIC;
-}
-
-static int
-gtk_mnemonic_trigger_compare (GtkShortcutTrigger  *trigger1,
-                              GtkShortcutTrigger  *trigger2)
-{
-  GtkMnemonicTrigger *self1 = (GtkMnemonicTrigger *) trigger1;
-  GtkMnemonicTrigger *self2 = (GtkMnemonicTrigger *) trigger2;
-
-  return self1->keyval - self2->keyval;
-}
-
-static void
-gtk_mnemonic_trigger_print (GtkShortcutTrigger *trigger,
-                            GString            *string)
-{
-  GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-  const char *keyval_str;
-
-  keyval_str = gdk_keyval_name (self->keyval);
-  if (keyval_str == NULL)
-    keyval_str = "???";
-
-  g_string_append (string, "<Mnemonic>");
-  g_string_append (string, keyval_str);
-}
-
-static gboolean
-gtk_mnemonic_trigger_print_label (GtkShortcutTrigger *trigger,
-                                  GdkDisplay         *display,
-                                  GString            *string)
-{
-  GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-  const char *keyval_str;
-
-  keyval_str = gdk_keyval_name (self->keyval);
-  if (keyval_str == NULL)
-    return FALSE;
-
-  g_string_append (string, keyval_str);
-
-  return TRUE;
-}
-
-static const GtkShortcutTriggerClass GTK_MNEMONIC_TRIGGER_CLASS = {
-  GTK_SHORTCUT_TRIGGER_MNEMONIC,
-  sizeof (GtkMnemonicTrigger),
-  "GtkMnemonicTrigger",
-  gtk_mnemonic_trigger_finalize,
-  gtk_mnemonic_trigger_trigger,
-  gtk_mnemonic_trigger_hash,
-  gtk_mnemonic_trigger_compare,
-  gtk_mnemonic_trigger_print,
-  gtk_mnemonic_trigger_print_label
-};
-
-/**
- * gtk_mnemonic_trigger_new:
- * @keyval: The keyval to trigger for
- *
- * Creates a #GtkShortcutTrigger that will trigger whenever the key with
- * the given @keyval is pressed and mnemonics have been activated.
- *
- * Mnemonics are activated by calling code when a key event with the right
- * modifiers is detected.
- *
- * Returns: A new #GtkShortcutTrigger
- */
-GtkShortcutTrigger *
-gtk_mnemonic_trigger_new (guint keyval)
-{
-  GtkMnemonicTrigger *self;
-
-  self = (GtkMnemonicTrigger *) gtk_shortcut_trigger_new (&GTK_MNEMONIC_TRIGGER_CLASS);
-
-  /* We store keyvals as lower key */
-  if (keyval == GDK_KEY_ISO_Left_Tab)
-    self->keyval = GDK_KEY_Tab;
-  else
-    self->keyval = gdk_keyval_to_lower (keyval);
-
-  return &self->trigger;
-}
-
-/**
- * gtk_mnemonic_trigger_get_keyval:
- * @trigger: a mnemonic #GtkShortcutTrigger
- *
- * Gets the keyval that must be pressed to succeed triggering @self.
- *
- * Returns: the keyval
- **/
-guint
-gtk_mnemonic_trigger_get_keyval (GtkShortcutTrigger *trigger)
-{
-  GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (trigger, GTK_SHORTCUT_TRIGGER_MNEMONIC), 0);
-
-  return self->keyval;
-}
-
-/*** GTK_ALTERNATIVE_TRIGGER ***/
-
-typedef struct _GtkAlternativeTrigger GtkAlternativeTrigger;
-
-struct _GtkAlternativeTrigger
-{
-  GtkShortcutTrigger trigger;
-
-  GtkShortcutTrigger *first;
-  GtkShortcutTrigger *second;
-};
-
-static void
-gtk_alternative_trigger_finalize (GtkShortcutTrigger *trigger)
-{
-  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
-  gtk_shortcut_trigger_unref (self->first);
-  gtk_shortcut_trigger_unref (self->second);
-}
-
-static gboolean
-gtk_alternative_trigger_trigger (GtkShortcutTrigger *trigger,
-                                 GdkEvent           *event,
-                                 gboolean            enable_mnemonics)
-{
-  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
-  if (gtk_shortcut_trigger_trigger (self->first, event, enable_mnemonics))
-    return TRUE;
-
-  if (gtk_shortcut_trigger_trigger (self->second, event, enable_mnemonics))
-    return TRUE;
-
-  return FALSE;
-}
-
-static guint
-gtk_alternative_trigger_hash (GtkShortcutTrigger *trigger)
-{
-  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-  guint result;
-
-  result = gtk_shortcut_trigger_hash (self->first);
-  result <<= 5;
-
-  result |= gtk_shortcut_trigger_hash (self->second);
-  result <<= 5;
-
-  return result | GTK_SHORTCUT_TRIGGER_ALTERNATIVE;
-}
-
-static int
-gtk_alternative_trigger_compare (GtkShortcutTrigger  *trigger1,
-                                 GtkShortcutTrigger  *trigger2)
-{
-  GtkAlternativeTrigger *self1 = (GtkAlternativeTrigger *) trigger1;
-  GtkAlternativeTrigger *self2 = (GtkAlternativeTrigger *) trigger2;
-  int cmp;
-
-  cmp = gtk_shortcut_trigger_compare (self1->first, self2->first);
-  if (cmp != 0)
-    return cmp;
-
-  return gtk_shortcut_trigger_compare (self1->second, self2->second);
-}
-
-static void
-gtk_alternative_trigger_print (GtkShortcutTrigger *trigger,
-                               GString            *string)
-{
-  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
-  gtk_shortcut_trigger_print (self->first, string);
-  g_string_append (string, ", ");
-  gtk_shortcut_trigger_print (self->second, string);
-}
-
-static gboolean
-gtk_alternative_trigger_print_label (GtkShortcutTrigger *trigger,
-                                     GdkDisplay         *display,
-                                     GString            *string)
-{
-  GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
-  if (gtk_shortcut_trigger_print_label (self->first, display, string))
-    {
-      g_string_append (string, ", ");
-      if (!gtk_shortcut_trigger_print_label (self->second, display, string))
-        g_string_truncate (string, string->len - 2);
-      return TRUE;
-    }
-  else
-    {
-      return gtk_shortcut_trigger_print_label (self->second, display, string);
-    }
-}
-
-static const GtkShortcutTriggerClass GTK_ALTERNATIVE_TRIGGER_CLASS = {
-  GTK_SHORTCUT_TRIGGER_ALTERNATIVE,
-  sizeof (GtkAlternativeTrigger),
-  "GtkAlternativeTrigger",
-  gtk_alternative_trigger_finalize,
-  gtk_alternative_trigger_trigger,
-  gtk_alternative_trigger_hash,
-  gtk_alternative_trigger_compare,
-  gtk_alternative_trigger_print,
-  gtk_alternative_trigger_print_label
-};
-
-/**
- * gtk_alternative_trigger_new:
- * @first: (transfer full): The first trigger that may trigger
- * @second: (transfer full): The second trigger that may trigger
- *
- * Creates a #GtkShortcutTrigger that will trigger whenever
- * either of the two given triggers gets triggered.
- *
- * Note that nesting is allowed, so if you want more than two
- * alternative, create a new alternative trigger for each option.
- *
- * Returns: a new #GtkShortcutTrigger
- */
-GtkShortcutTrigger *
-gtk_alternative_trigger_new (GtkShortcutTrigger *first,
-                             GtkShortcutTrigger *second)
-{
-  GtkAlternativeTrigger *self;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (first), NULL);
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (second), NULL);
-
-  self = (GtkAlternativeTrigger *) gtk_shortcut_trigger_new (&GTK_ALTERNATIVE_TRIGGER_CLASS);
-
-  self->first = first;
-  self->second = second;
-
-  return &self->trigger;
-}
-
-/**
- * gtk_alternative_trigger_get_first:
- * @self: an alternative #GtkShortcutTrigger
- *
- * Gets the first of the two alternative triggers that may
- * trigger @self. gtk_alternative_trigger_get_second() will
- * return the other one.
- *
- * Returns: (transfer none): the first alternative trigger
- **/
-GtkShortcutTrigger *
-gtk_alternative_trigger_get_first (GtkShortcutTrigger *self)
-{
-  GtkAlternativeTrigger *trigger = (GtkAlternativeTrigger *) self;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_ALTERNATIVE), 0);
-
-  return trigger->first;
-}
-
-/**
- * gtk_alternative_trigger_get_second:
- * @self: an alternative #GtkShortcutTrigger
- *
- * Gets the second of the two alternative triggers that may
- * trigger @self. gtk_alternative_trigger_get_first() will
- * return the other one.
- *
- * Returns: (transfer none): the second alternative trigger
- **/
-GtkShortcutTrigger *
-gtk_alternative_trigger_get_second (GtkShortcutTrigger *self)
-{
-  GtkAlternativeTrigger *trigger = (GtkAlternativeTrigger *) self;
-
-  g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_ALTERNATIVE), 0);
-
-  return trigger->second;
-}
diff --git a/gtk/gtkshortcuttrigger.h b/gtk/gtkshortcuttrigger.h
deleted file mode 100644 (file)
index b0ab8af..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_TRIGGER_H__
-#define __GTK_SHORTCUT_TRIGGER_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_TRIGGER (gtk_shortcut_trigger_get_type ())
-
-#define GTK_IS_SHORTCUT_TRIGGER(obj) ((obj) != NULL)
-
-/**
- * GtkShortcutTriggerType:
- * @GTK_SHORTCUT_TRIGGER_NEVER: Never ever trigger
- * @GTK_SHORTCUT_TRIGGER_KEYVAL: Trigger if a key event with matching
- *     modifiers and keyval is received.
- * @GTK_SHORTCUT_TRIGGER_MNEMONIC: Trigger if a key event with matching
- *     keyval is received and mnemonics are enabled for this event.
- * @GTK_SHORTCUT_TRIGGER_ALTERNAITVE: Trigger if either if two
- *     alternatives triggers
- *
- * The type of a trigger determines what the trigger triggers on.
- **/
-typedef enum {
-  GTK_SHORTCUT_TRIGGER_NEVER,
-  GTK_SHORTCUT_TRIGGER_KEYVAL,
-  GTK_SHORTCUT_TRIGGER_MNEMONIC,
-  GTK_SHORTCUT_TRIGGER_ALTERNATIVE
-} GtkShortcutTriggerType;
-
-GDK_AVAILABLE_IN_ALL
-GType                   gtk_shortcut_trigger_get_type           (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_shortcut_trigger_ref                (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_trigger_unref              (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTriggerType  gtk_shortcut_trigger_get_trigger_type   (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_shortcut_trigger_parse_string       (const char         *string);
-
-GDK_AVAILABLE_IN_ALL
-char *                  gtk_shortcut_trigger_to_string          (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-void                    gtk_shortcut_trigger_print              (GtkShortcutTrigger *self,
-                                                                 GString            *string);
-GDK_AVAILABLE_IN_ALL
-char *                  gtk_shortcut_trigger_to_label           (GtkShortcutTrigger *self,
-                                                                 GdkDisplay         *display);
-GDK_AVAILABLE_IN_ALL
-gboolean                gtk_shortcut_trigger_print_label        (GtkShortcutTrigger *self,
-                                                                 GdkDisplay         *display,
-                                                                 GString            *string);
-
-GDK_AVAILABLE_IN_ALL
-guint                   gtk_shortcut_trigger_hash               (gconstpointer       trigger);
-GDK_AVAILABLE_IN_ALL
-gboolean                gtk_shortcut_trigger_equal              (gconstpointer       trigger1,
-                                                                 gconstpointer       trigger2);
-GDK_AVAILABLE_IN_ALL
-gint                    gtk_shortcut_trigger_compare            (gconstpointer       trigger1,
-                                                                 gconstpointer       trigger2);
-
-GDK_AVAILABLE_IN_ALL
-gboolean                gtk_shortcut_trigger_trigger            (GtkShortcutTrigger *self,
-                                                                 GdkEvent           *event,
-                                                                 gboolean            enable_mnemonics);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_never_trigger_get                   (void);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_keyval_trigger_new                  (guint               keyval,
-                                                                 GdkModifierType     modifiers);
-GDK_AVAILABLE_IN_ALL
-GdkModifierType         gtk_keyval_trigger_get_modifiers        (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-guint                   gtk_keyval_trigger_get_keyval           (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_mnemonic_trigger_new                (guint               keyval);
-GDK_AVAILABLE_IN_ALL
-guint                   gtk_mnemonic_trigger_get_keyval         (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_alternative_trigger_new             (GtkShortcutTrigger *one,
-                                                                 GtkShortcutTrigger *two);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_alternative_trigger_get_first       (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *    gtk_alternative_trigger_get_second      (GtkShortcutTrigger *self);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_TRIGGER_H__ */
index 0176797f1e8c79b4431413713cd2f47c67ae4b58..548bac5f16ea725290f09b2abb55d8fdd4f82f10 100644 (file)
@@ -30,6 +30,7 @@
 #include "gtkspinbutton.h"
 
 #include "gtkadjustment.h"
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkbutton.h"
 #include "gtkcssstylepropertyprivate.h"
@@ -316,10 +317,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkSpinButton, gtk_spin_button, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
                                                 gtk_spin_button_cell_editable_init))
 
-#define add_spin_binding(widget_class, keyval, mask, scroll)            \
-  gtk_widget_class_add_binding_signal (widget_class, keyval, mask,      \
-                                       "change-value",                  \
-                                       "(i)", scroll)
+#define add_spin_binding(binding_set, keyval, mask, scroll)            \
+  gtk_binding_entry_add_signal (binding_set, keyval, mask,             \
+                                "change-value", 1,                     \
+                                GTK_TYPE_SCROLL_TYPE, scroll)
 
 
 static gboolean
@@ -346,6 +347,7 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
 {
   GObjectClass     *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass   *widget_class = GTK_WIDGET_CLASS (class);
+  GtkBindingSet    *binding_set;
 
   gobject_class->finalize = gtk_spin_button_finalize;
   gobject_class->set_property = gtk_spin_button_set_property;
@@ -543,16 +545,18 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
                   G_TYPE_NONE, 1,
                   GTK_TYPE_SCROLL_TYPE);
 
-  add_spin_binding (widget_class, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
-  add_spin_binding (widget_class, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
-  add_spin_binding (widget_class, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
-  add_spin_binding (widget_class, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
-  add_spin_binding (widget_class, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
-  add_spin_binding (widget_class, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_DOWN);
-  add_spin_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK, GTK_SCROLL_END);
-  add_spin_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START);
-  add_spin_binding (widget_class, GDK_KEY_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_END);
-  add_spin_binding (widget_class, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_START);
+  binding_set = gtk_binding_set_by_class (class);
+
+  add_spin_binding (binding_set, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
+  add_spin_binding (binding_set, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
+  add_spin_binding (binding_set, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
+  add_spin_binding (binding_set, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
+  add_spin_binding (binding_set, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+  add_spin_binding (binding_set, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_DOWN);
+  add_spin_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK, GTK_SCROLL_END);
+  add_spin_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START);
+  add_spin_binding (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_END);
+  add_spin_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_START);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SPIN_BUTTON_ACCESSIBLE);
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
index 70a5d5276c3fc7df201335a429ae8638fde9d31e..b052cebb62d84c12c75e7fc06174acf4626a33cd 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "gtkactionable.h"
 #include "gtkadjustment.h"
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkbutton.h"
 #include "gtkcssnodeprivate.h"
@@ -381,9 +382,7 @@ static void        gtk_text_set_alignment        (GtkText    *self,
 /* Default signal handlers
  */
 static GMenuModel *gtk_text_get_menu_model  (GtkText         *self);
-static void     gtk_text_popup_menu         (GtkWidget       *widget,
-                                             const char      *action_name,
-                                             GVariant        *parameters);
+static gboolean gtk_text_popup_menu         (GtkWidget       *widget);
 static void     gtk_text_move_cursor        (GtkText         *self,
                                              GtkMovementStep  step,
                                              int              count,
@@ -680,7 +679,7 @@ G_DEFINE_TYPE_WITH_CODE (GtkText, gtk_text, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_text_editable_init))
 
 static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet  *binding_set,
                   guint           keyval,
                   guint           modmask,
                   GtkMovementStep step,
@@ -688,22 +687,28 @@ add_move_binding (GtkWidgetClass *widget_class,
 {
   g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                       "move-cursor",
-                                       "(iib)", step, count, FALSE);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                                "move-cursor", 3,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count,
+                                G_TYPE_BOOLEAN, FALSE);
+
   /* Selection-extending version */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | GDK_SHIFT_MASK,
-                                       "move-cursor",
-                                       "(iib)", step, count, TRUE);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
+                                "move-cursor", 3,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count,
+                                G_TYPE_BOOLEAN, TRUE);
 }
 
 static void
 gtk_text_class_init (GtkTextClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GtkWidgetClass *widget_class;
+  GtkBindingSet *binding_set;
+
+  widget_class = (GtkWidgetClass*) class;
 
   gobject_class->dispose = gtk_text_dispose;
   gobject_class->finalize = gtk_text_finalize;
@@ -723,6 +728,7 @@ gtk_text_class_init (GtkTextClass *class)
   widget_class->state_flags_changed = gtk_text_state_flags_changed;
   widget_class->root = gtk_text_root;
   widget_class->mnemonic_activate = gtk_text_mnemonic_activate;
+  widget_class->popup_menu = gtk_text_popup_menu;
 
   class->move_cursor = gtk_text_move_cursor;
   class->insert_at_cursor = gtk_text_insert_at_cursor;
@@ -1190,217 +1196,187 @@ gtk_text_class_init (GtkTextClass *class)
 
   gtk_widget_class_install_action (widget_class, "text.undo", NULL, gtk_text_real_undo);
   gtk_widget_class_install_action (widget_class, "text.redo", NULL, gtk_text_real_redo);
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_text_popup_menu);
 
   /*
    * Key bindings
    */
 
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
+  binding_set = gtk_binding_set_by_class (class);
 
   /* Moving the insertion point */
-  add_move_binding (widget_class, GDK_KEY_Right, 0,
+  add_move_binding (binding_set, GDK_KEY_Right, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Left, 0,
+  add_move_binding (binding_set, GDK_KEY_Left, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Home, 0,
+  add_move_binding (binding_set, GDK_KEY_Home, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_End, 0,
+  add_move_binding (binding_set, GDK_KEY_End, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_End, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_End, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, 1);
 
   /* Select all
    */
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_a, GDK_CONTROL_MASK,
-                                (GtkShortcutFunc) gtk_text_select_all,
-                                NULL);
-
-  gtk_widget_class_add_binding (widget_class,
-                                GDK_KEY_slash, GDK_CONTROL_MASK,
-                                (GtkShortcutFunc) gtk_text_select_all,
-                                NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                                "move-cursor", 3,
+                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+                                G_TYPE_INT, -1,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                                "move-cursor", 3,
+                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+                                G_TYPE_INT, 1,
+                                G_TYPE_BOOLEAN, TRUE);  
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+                                "move-cursor", 3,
+                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+                                G_TYPE_INT, -1,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+                                "move-cursor", 3,
+                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+                                G_TYPE_INT, 1,
+                                G_TYPE_BOOLEAN, TRUE);  
   /* Unselect all 
    */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_backslash, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(iib)", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(iib)", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
+                                "move-cursor", 3,
+                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
+                                G_TYPE_INT, 0,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                                "move-cursor", 3,
+                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
+                                G_TYPE_INT, 0,
+                                G_TYPE_BOOLEAN, FALSE);
 
   /* Activate
    */
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
-                                       "activate",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
-                                       "activate",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
-                                       "activate",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+                                "activate", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+                                "activate", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+                                "activate", 0);
   
   /* Deleting text */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, 0,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_CHARS, 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, 0,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_CHARS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
+                                "delete-from-cursor", 2,
+                                G_TYPE_ENUM, GTK_DELETE_CHARS,
+                                G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
+                                "delete-from-cursor", 2,
+                                G_TYPE_ENUM, GTK_DELETE_CHARS,
+                                G_TYPE_INT, 1);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, 0,
-                                       "backspace",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
+                                "backspace", 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_u, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_PARAGRAPH_ENDS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_u, GDK_CONTROL_MASK,
+                                "delete-from-cursor", 2,
+                                G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                                G_TYPE_INT, -1);
 
   /* Make this do the same as Backspace, to help with mis-typing */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, GDK_SHIFT_MASK,
-                                       "backspace",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_WORD_ENDS, 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_WORD_ENDS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
+                                "backspace", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
+                                "delete-from-cursor", 2,
+                                G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+                                G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
+                                "delete-from-cursor", 2,
+                                G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+                                G_TYPE_INT, 1);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_WORD_ENDS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK,
+                                "delete-from-cursor", 2,
+                                G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+                                G_TYPE_INT, -1);
 
   /* Cut/copy/paste */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_x, GDK_CONTROL_MASK,
-                                       "cut-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_c, GDK_CONTROL_MASK,
-                                       "copy-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_v, GDK_CONTROL_MASK,
-                                       "paste-clipboard",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, GDK_SHIFT_MASK,
-                                       "cut-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Insert, GDK_CONTROL_MASK,
-                                       "copy-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Insert, GDK_SHIFT_MASK,
-                                       "paste-clipboard",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
-                                       "cut-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
-                                       "copy-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
-                                       "paste-clipboard",
-                                       NULL);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
+                                "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
+                                "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
+                                "paste-clipboard", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
+                                "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK,
+                                "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK,
+                                "paste-clipboard", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
+                                "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
+                                "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
+                                "paste-clipboard", 0);
 
   /* Overwrite */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Insert, 0,
-                                       "toggle-overwrite",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Insert, 0,
-                                       "toggle-overwrite",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0,
+                                "toggle-overwrite", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
+                                "toggle-overwrite", 0);
 
   /* Emoji */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_period, GDK_CONTROL_MASK,
-                                       "insert-emoji",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_semicolon, GDK_CONTROL_MASK,
-                                       "insert-emoji",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_period, GDK_CONTROL_MASK,
+                                "insert-emoji", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_semicolon, GDK_CONTROL_MASK,
+                                "insert-emoji", 0);
 
   /* Undo/Redo */
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_z, GDK_CONTROL_MASK,
-                                       "text.undo", NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_y, GDK_CONTROL_MASK,
-                                       "text.redo", NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "text.redo", NULL);
-
+  gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK,
+                                "text.undo", NULL);
+  gtk_binding_entry_add_action (binding_set, GDK_KEY_y, GDK_CONTROL_MASK,
+                                "text.redo", NULL);
+  gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "text.redo", NULL);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("text"));
@@ -5936,12 +5912,11 @@ gtk_text_mnemonic_activate (GtkWidget *widget,
   return GDK_EVENT_STOP;
 }
 
-static void
-gtk_text_popup_menu (GtkWidget  *widget,
-                     const char *action_name,
-                     GVariant   *parameters)
+static gboolean
+gtk_text_popup_menu (GtkWidget *widget)
 {
   gtk_text_do_popup (GTK_TEXT (widget), -1, -1);
+  return TRUE;
 }
 
 static void
index 60842f76f5ea5f9466e0feb75f2eac1d781a7ea4..62687d0f294ec6ed169f05a98996493792a0179d 100644 (file)
@@ -30,6 +30,7 @@
 #include <string.h>
 
 #include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkdebug.h"
 #include "gtkdropcontrollermotion.h"
@@ -434,9 +435,7 @@ static gboolean gtk_text_view_drag_drop          (GtkDropTarget    *dest,
                                                   double            y,
                                                   GtkTextView      *text_view);
 
-static void gtk_text_view_popup_menu        (GtkWidget  *widget,
-                                             const char *action_name,
-                                             GVariant   *parameters);
+static gboolean gtk_text_view_popup_menu         (GtkWidget     *widget);
 static void gtk_text_view_move_cursor       (GtkTextView           *text_view,
                                              GtkMovementStep        step,
                                              gint                   count,
@@ -775,7 +774,7 @@ gtk_text_view_drop_scroll_leave (GtkDropControllerMotion *motion,
 }
 
 static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet  *binding_set,
                   guint           keyval,
                   guint           modmask,
                   GtkMovementStep step,
@@ -783,16 +782,18 @@ add_move_binding (GtkWidgetClass *widget_class,
 {
   g_assert ((modmask & GDK_SHIFT_MASK) == 0);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                       "move-cursor",
-                                       "(iib)", step, count, FALSE);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                                "move-cursor", 3,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count,
+                                G_TYPE_BOOLEAN, FALSE);
 
   /* Selection-extending version */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask | GDK_SHIFT_MASK,
-                                       "move-cursor",
-                                       "(iib)", step, count, TRUE);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
+                                "move-cursor", 3,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count,
+                                G_TYPE_BOOLEAN, TRUE);
 }
 
 static void
@@ -801,6 +802,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   /* Default handlers and virtual methods
    */
@@ -820,6 +822,8 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
   widget_class->snapshot = gtk_text_view_snapshot;
   widget_class->focus = gtk_text_view_focus;
 
+  widget_class->popup_menu = gtk_text_view_popup_menu;
+
   container_class->add = gtk_text_view_add;
   container_class->remove = gtk_text_view_remove;
   container_class->forall = gtk_text_view_forall;
@@ -1462,288 +1466,237 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
 
   gtk_widget_class_install_action (widget_class, "text.undo", NULL, gtk_text_view_real_undo);
   gtk_widget_class_install_action (widget_class, "text.redo", NULL, gtk_text_view_real_redo);
-  gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_text_view_popup_menu);
 
   /*
    * Key bindings
    */
 
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_F10, GDK_SHIFT_MASK,
-                                       "menu.popup",
-                                       NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_Menu, 0,
-                                       "menu.popup",
-                                       NULL);
-
+  binding_set = gtk_binding_set_by_class (klass);
+  
   /* Moving the insertion point */
-  add_move_binding (widget_class, GDK_KEY_Right, 0,
+  add_move_binding (binding_set, GDK_KEY_Right, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Left, 0,
+  add_move_binding (binding_set, GDK_KEY_Left, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
                     GTK_MOVEMENT_VISUAL_POSITIONS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_WORDS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Up, 0,
+  add_move_binding (binding_set, GDK_KEY_Up, 0,
                     GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
                     GTK_MOVEMENT_DISPLAY_LINES, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Down, 0,
+  add_move_binding (binding_set, GDK_KEY_Down, 0,
                     GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
                     GTK_MOVEMENT_DISPLAY_LINES, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Up, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_PARAGRAPHS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_PARAGRAPHS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Down, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_PARAGRAPHS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Down, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Down, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_PARAGRAPHS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Home, 0,
+  add_move_binding (binding_set, GDK_KEY_Home, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_End, 0,
+  add_move_binding (binding_set, GDK_KEY_End, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_End, 0,
                     GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, -1);
   
-  add_move_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_End, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_BUFFER_ENDS, 1);
   
-  add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+  add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
                     GTK_MOVEMENT_PAGES, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
                     GTK_MOVEMENT_PAGES, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+  add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
                     GTK_MOVEMENT_PAGES, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+  add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
                     GTK_MOVEMENT_PAGES, 1);
 
-  add_move_binding (widget_class, GDK_KEY_Page_Up, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_HORIZONTAL_PAGES, -1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Page_Up, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Page_Up, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_HORIZONTAL_PAGES, -1);
   
-  add_move_binding (widget_class, GDK_KEY_Page_Down, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_HORIZONTAL_PAGES, 1);
 
-  add_move_binding (widget_class, GDK_KEY_KP_Page_Down, GDK_CONTROL_MASK,
+  add_move_binding (binding_set, GDK_KEY_KP_Page_Down, GDK_CONTROL_MASK,
                     GTK_MOVEMENT_HORIZONTAL_PAGES, 1);
 
   /* Select all */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_CONTROL_MASK,
-                                       "select-all",
-                                       "(b)", TRUE);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_slash, GDK_CONTROL_MASK,
-                                       "select-all",
-                                       "(b)", TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+                               "select-all", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+                               "select-all", 1,
+                               G_TYPE_BOOLEAN, TRUE);
   
   /* Unselect all */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_backslash, GDK_CONTROL_MASK,
-                                       "select-all",
-                                       "(b)", FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
+                                "select-all", 1,
+                                G_TYPE_BOOLEAN, FALSE);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "select-all",
-                                       "(b)", FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                                "select-all", 1,
+                                G_TYPE_BOOLEAN, FALSE);
 
   /* Deleting text */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, 0,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_CHARS, 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, 0,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_CHARS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_CHARS,
+                               G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_CHARS,
+                               G_TYPE_INT, 1);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, 0,
-                                       "backspace",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
+                               "backspace", 0);
 
   /* Make this do the same as Backspace, to help with mis-typing */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, GDK_SHIFT_MASK,
-                                       "backspace",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_WORD_ENDS, 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_WORD_ENDS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
+                               "backspace", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+                               G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+                               G_TYPE_INT, 1);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_WORD_ENDS, -1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_PARAGRAPH_ENDS, 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_PARAGRAPH_ENDS, 1);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_BackSpace, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "delete-from-cursor",
-                                       "(ii)", GTK_DELETE_PARAGRAPH_ENDS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+                               G_TYPE_INT, -1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                               G_TYPE_INT, -1);
 
   /* Cut/copy/paste */
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_x, GDK_CONTROL_MASK,
-                                       "cut-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_c, GDK_CONTROL_MASK,
-                                       "copy-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_v, GDK_CONTROL_MASK,
-                                       "paste-clipboard",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
-                                       "cut-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
-                                       "copy-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
-                                       "paste-clipboard",
-                                       NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Delete, GDK_SHIFT_MASK,
-                                       "cut-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Insert, GDK_CONTROL_MASK,
-                                       "copy-clipboard",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Insert, GDK_SHIFT_MASK,
-                                       "paste-clipboard",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
+                               "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
+                               "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
+                               "paste-clipboard", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
+                               "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
+                               "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
+                               "paste-clipboard", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
+                                "cut-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK,
+                                "copy-clipboard", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK,
+                                "paste-clipboard", 0);
 
   /* Undo/Redo */
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_z, GDK_CONTROL_MASK,
-                                       "text.undo", NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_y, GDK_CONTROL_MASK,
-                                       "text.redo", NULL);
-  gtk_widget_class_add_binding_action (widget_class,
-                                       GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "text.redo", NULL);
+  gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK,
+                                "text.undo", NULL);
+  gtk_binding_entry_add_action (binding_set, GDK_KEY_y, GDK_CONTROL_MASK,
+                                "text.redo", NULL);
+  gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "text.redo", NULL);
 
   /* Overwrite */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Insert, 0,
-                                       "toggle-overwrite",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Insert, 0,
-                                       "toggle-overwrite",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0,
+                               "toggle-overwrite", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
+                               "toggle-overwrite", 0);
 
   /* Emoji */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_period, GDK_CONTROL_MASK,
-                                       "insert-emoji",
-                                       NULL);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_semicolon, GDK_CONTROL_MASK,
-                                       "insert-emoji",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_period, GDK_CONTROL_MASK,
+                                "insert-emoji", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_semicolon, GDK_CONTROL_MASK,
+                                "insert-emoji", 0);
 
   /* Caret mode */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_F7, 0,
-                                       "toggle-cursor-visible",
-                                       NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_F7, 0,
+                               "toggle-cursor-visible", 0);
 
   /* Control-tab focus motion */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Tab, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)", GTK_DIR_TAB_FORWARD);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Tab, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)", GTK_DIR_TAB_FORWARD);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, GDK_CONTROL_MASK,
+                               "move-focus", 1,
+                               GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, GDK_CONTROL_MASK,
+                               "move-focus", 1,
+                               GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)", GTK_DIR_TAB_BACKWARD);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)", GTK_DIR_TAB_BACKWARD);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "move-focus", 1,
+                               GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "move-focus", 1,
+                               GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_VIEW_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("textview"));
@@ -4475,9 +4428,6 @@ gtk_text_view_size_allocate (GtkWidget *widget,
 
   if (priv->popup_menu)
     gtk_native_check_resize (GTK_NATIVE (priv->popup_menu));
-
-  if (priv->selection_bubble)
-    gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble));
 }
 
 static void
@@ -8705,12 +8655,11 @@ gtk_text_view_do_popup (GtkTextView    *text_view,
     gdk_event_unref (trigger_event);
 }
 
-static void
-gtk_text_view_popup_menu (GtkWidget  *widget,
-                          const char *action_name,
-                          GVariant   *parameters)
+static gboolean
+gtk_text_view_popup_menu (GtkWidget *widget)
 {
   gtk_text_view_do_popup (GTK_TEXT_VIEW (widget), NULL);
+  return TRUE;
 }
 
 static void
index 51fa6d52298f2e5978dcdcaa7584f8c863579e62..a30d0c09737a97bfae8ddeb274344352b494e513 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "gtkadjustmentprivate.h"
 #include "gtkbox.h"
+#include "gtkbindings.h"
 #include "gtkbuildable.h"
 #include "gtkbutton.h"
 #include "gtkcelllayout.h"
@@ -53,7 +54,6 @@
 #include "gtkrendericonprivate.h"
 #include "gtkscrollable.h"
 #include "gtksettingsprivate.h"
-#include "gtkshortcutcontroller.h"
 #include "gtksnapshot.h"
 #include "gtkstylecontextprivate.h"
 #include "gtktooltip.h"
@@ -657,11 +657,6 @@ static void     gtk_tree_view_size_allocate        (GtkWidget      *widget,
 static void     gtk_tree_view_snapshot             (GtkWidget        *widget,
                                                     GtkSnapshot      *snapshot);
 
-static gboolean gtk_tree_view_forward_controller_key_pressed  (GtkEventControllerKey *key,
-                                                               guint                  keyval,
-                                                               guint                  keycode,
-                                                               GdkModifierType        state,
-                                                               GtkTreeView           *tree_view);
 static gboolean gtk_tree_view_key_controller_key_pressed  (GtkEventControllerKey *key,
                                                            guint                  keyval,
                                                            guint                  keycode,
@@ -770,7 +765,7 @@ static void     invalidate_empty_focus      (GtkTreeView *tree_view);
 static gboolean gtk_tree_view_is_expander_column             (GtkTreeView        *tree_view,
                                                              GtkTreeViewColumn  *column);
 static inline gboolean gtk_tree_view_draw_expanders          (GtkTreeView        *tree_view);
-static void     gtk_tree_view_add_move_binding               (GtkWidgetClass     *widget_class,
+static void     gtk_tree_view_add_move_binding               (GtkBindingSet      *binding_set,
                                                              guint               keyval,
                                                              guint               modmask,
                                                              gboolean            add_shifted_binding,
@@ -1004,9 +999,16 @@ G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
 static void
 gtk_tree_view_class_init (GtkTreeViewClass *class)
 {
-  GObjectClass *o_class = G_OBJECT_CLASS (class);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+  GObjectClass *o_class;
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+  GtkBindingSet *binding_set;
+
+  binding_set = gtk_binding_set_by_class (class);
+
+  o_class = (GObjectClass *) class;
+  widget_class = (GtkWidgetClass *) class;
+  container_class = (GtkContainerClass *) class;
 
   /* GObject signals */
   o_class->set_property = gtk_tree_view_set_property;
@@ -1501,198 +1503,217 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                               _gtk_marshal_BOOLEAN__VOIDv);
 
   /* Key bindings */
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Up, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Up, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Up, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Down, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Down, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Down, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0, TRUE,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_p, GDK_CONTROL_MASK, FALSE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK, FALSE,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_n, GDK_CONTROL_MASK, FALSE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK, FALSE,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Home, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Home, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Home, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_End, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_End, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_End, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0, TRUE,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Page_Up, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, -1);
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, -1);
 
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Page_Down, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, 1);
-  gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0, TRUE,
+  gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0, TRUE,
                                  GTK_MOVEMENT_PAGES, 1);
 
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Right, 0,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, 0, "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Left, 0,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, 0, "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Right, 0,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, 0, "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Left, 0,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, 0, "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Right, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
+                                "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Left, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
+                                "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Right, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+                                "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Left, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+                                "move-cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, GDK_CONTROL_MASK, "toggle-cursor-row", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_a, GDK_CONTROL_MASK, "select-all", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_slash, GDK_CONTROL_MASK, "select-all", NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "select-all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK, "select-all", 0);
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_backslash, GDK_CONTROL_MASK, "unselect-all", NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK, "unselect-all", 0);
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, GDK_SHIFT_MASK, "select-cursor-row", "(b)", TRUE);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", "(b)", TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_SHIFT_MASK, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0, "select-cursor-row", "(b)", TRUE);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0, "select-cursor-row", "(b)", TRUE);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0, "select-cursor-row", "(b)", TRUE);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0, "select-cursor-row", "(b)", TRUE);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0, "select-cursor-row", "(b)", TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "select-cursor-row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
 
   /* expand and collapse rows */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_plus, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, FALSE);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_asterisk, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Multiply, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, TRUE);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_slash, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, FALSE, FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Divide, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, FALSE, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, 0, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_asterisk, 0,
+                                "expand-collapse-cursor-row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Multiply, 0,
+                                "expand-collapse-cursor-row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, 0,
+                                "expand-collapse-cursor-row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, FALSE,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Divide, 0,
+                                "expand-collapse-cursor-row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, FALSE,
+                                G_TYPE_BOOLEAN, FALSE);
 
   /* Not doable on US keyboards */
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_plus, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Add, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Add, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Add, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Right, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Right, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Right, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, TRUE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Right, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, TRUE, TRUE);
-
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_minus, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, FALSE, FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_minus, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, FALSE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Subtract, 0,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, FALSE, FALSE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Subtract, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", TRUE, FALSE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Left, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, FALSE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Left, GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, FALSE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_Left, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, FALSE, TRUE);
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       GDK_KEY_KP_Left, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "expand-collapse-cursor-row",
-                                       "(bbb)", FALSE, FALSE, TRUE);
-
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_BackSpace, 0, "select-cursor-parent", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_f, GDK_CONTROL_MASK, "start-interactive-search", NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_F, GDK_CONTROL_MASK, "start-interactive-search", NULL);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, 0, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, 0, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Subtract, 0, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Subtract, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand-collapse-cursor-row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0, "select-cursor-parent", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_f, GDK_CONTROL_MASK, "start-interactive-search", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_F, GDK_CONTROL_MASK, "start-interactive-search", 0);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TREE_VIEW_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("treeview"));
@@ -1704,7 +1725,6 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   GtkCssNode *widget_node;
   GtkGesture *gesture;
   GtkEventController *controller;
-  GList *list, *controllers;
 
   gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
   gtk_widget_set_overflow (GTK_WIDGET (tree_view), GTK_OVERFLOW_HIDDEN);
@@ -1766,24 +1786,6 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   gtk_css_node_set_state (tree_view->header_node, gtk_css_node_get_state (widget_node));
   g_object_unref (tree_view->header_node);
 
-  controller = gtk_event_controller_key_new ();
-  g_signal_connect (controller, "key-pressed",
-                    G_CALLBACK (gtk_tree_view_forward_controller_key_pressed), tree_view);
-  gtk_widget_add_controller (GTK_WIDGET (tree_view), controller);
-
-  controllers = gtk_widget_list_controllers (GTK_WIDGET (tree_view), GTK_PHASE_BUBBLE);
-  for (list = controllers; list; list = list->next)
-    {
-      if (GTK_IS_SHORTCUT_CONTROLLER (list->data))
-        {
-          g_object_ref (list->data);
-          gtk_widget_remove_controller (GTK_WIDGET (tree_view), list->data);
-          gtk_widget_add_controller (GTK_WIDGET (tree_view), list->data);
-          break;
-        }
-    }
-  g_list_free (controllers);
-
   tree_view->click_gesture = gtk_gesture_click_new ();
   gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (tree_view->click_gesture), 0);
   g_signal_connect (tree_view->click_gesture, "pressed",
@@ -5310,6 +5312,7 @@ gtk_tree_view_key_controller_key_pressed (GtkEventControllerKey *key,
 {
   GtkWidget *widget = GTK_WIDGET (tree_view);
   GtkWidget *button;
+  GdkEvent *event;
 
   if (tree_view->rubber_band_status)
     {
@@ -5429,16 +5432,16 @@ gtk_tree_view_key_controller_key_pressed (GtkEventControllerKey *key,
         }
     }
 
-  return FALSE;
-}
+  /* Handle the keybindings. */
+  event = gtk_get_current_event ();
+  if (gtk_bindings_activate_event (G_OBJECT (widget), event))
+    {
+      gdk_event_unref (event);
+      return TRUE;
+    }
+
+  gdk_event_unref (event);
 
-static gboolean
-gtk_tree_view_forward_controller_key_pressed (GtkEventControllerKey *key,
-                                              guint                  keyval,
-                                              guint                  keycode,
-                                              GdkModifierType        state,
-                                              GtkTreeView           *tree_view)
-{
   if (tree_view->search_entry_avoid_unhandled_binding)
     {
       tree_view->search_entry_avoid_unhandled_binding = FALSE;
@@ -5484,6 +5487,15 @@ gtk_tree_view_key_controller_key_released (GtkEventControllerKey *key,
                                            GdkModifierType        state,
                                            GtkTreeView           *tree_view)
 {
+  GdkEvent *event;
+
+  if (tree_view->rubber_band_status)
+    return;
+
+  /* Handle the keybindings. */
+  event = gtk_get_current_event ();
+  gtk_bindings_activate_event (G_OBJECT (tree_view), event);
+  gdk_event_unref (event);
 }
 
 static void
@@ -8902,7 +8914,7 @@ gtk_tree_view_draw_expanders (GtkTreeView *tree_view)
 }
 
 static void
-gtk_tree_view_add_move_binding (GtkWidgetClass *widget_class,
+gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
                                guint           keyval,
                                guint           modmask,
                                gboolean        add_shifted_binding,
@@ -8910,29 +8922,29 @@ gtk_tree_view_add_move_binding (GtkWidgetClass *widget_class,
                                gint            count)
 {
   
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, modmask,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+                                "move-cursor", 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   if (add_shifted_binding)
-    gtk_widget_class_add_binding_signal (widget_class,
-                                         keyval, GDK_SHIFT_MASK,
-                                         "move-cursor",
-                                         "(ii)", step, count);
+    gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
+                                 "move-cursor", 2,
+                                 G_TYPE_ENUM, step,
+                                 G_TYPE_INT, count);
 
   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
    return;
 
-  gtk_widget_class_add_binding_signal (widget_class, keyval,
-      GDK_CONTROL_MASK | GDK_SHIFT_MASK,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "move-cursor", 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
-  gtk_widget_class_add_binding_signal (widget_class,
-                                       keyval, GDK_CONTROL_MASK,
-                                       "move-cursor",
-                                       "(ii)", step, count);
+  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
+                                "move-cursor", 2,
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 }
 
 static gint
index 8edd13fcd176336d8a977a3f102113374e4118e3..a5ad190720022471820b9ae7d3d4c4929e958f94 100644 (file)
@@ -45,9 +45,6 @@ typedef struct _GtkNative              GtkNative;
 typedef struct _GtkRequisition        GtkRequisition;
 typedef struct _GtkRoot               GtkRoot;
 typedef struct _GtkSettings            GtkSettings;
-typedef struct _GtkShortcut            GtkShortcut;
-typedef struct _GtkShortcutAction      GtkShortcutAction;
-typedef struct _GtkShortcutTrigger     GtkShortcutTrigger;
 typedef GdkSnapshot                    GtkSnapshot;
 typedef struct _GtkStyleContext        GtkStyleContext;
 typedef struct _GtkTooltip             GtkTooltip;
index 8a02f96012b4292c77361b175626f08798be55ff..634a50dbea260c90026a40c99601c7290e846e16 100644 (file)
 
 #include "gtkwidgetprivate.h"
 
+#include "gtkaccelmapprivate.h"
 #include "gtkaccelgroupprivate.h"
 #include "gtkaccessible.h"
 #include "gtkapplicationprivate.h"
+#include "gtkbindings.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
-#include "gtkconcatmodelprivate.h"
 #include "gtkcontainerprivate.h"
 #include "gtkcssboxesprivate.h"
 #include "gtkcssfiltervalueprivate.h"
 #include "gtknativeprivate.h"
 #include "gtkscrollable.h"
 #include "gtksettingsprivate.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutcontrollerprivate.h"
-#include "gtkshortcutmanager.h"
-#include "gtkshortcutmanagerprivate.h"
-#include "gtkshortcuttrigger.h"
 #include "gtksizegroup-private.h"
 #include "gtksnapshotprivate.h"
 #include "gtkstylecontextprivate.h"
@@ -497,7 +493,6 @@ typedef struct {
 struct _GtkWidgetClassPrivate
 {
   GtkWidgetTemplate *template;
-  GListStore *shortcuts;
   GType accessible_type;
   AtkRole accessible_role;
   GQuark css_name;
@@ -520,6 +515,7 @@ enum {
   MNEMONIC_ACTIVATE,
   MOVE_FOCUS,
   KEYNAV_FAILED,
+  POPUP_MENU,
   ACCEL_CLOSURES_CHANGED,
   CAN_ACTIVATE_ACCEL,
   QUERY_TOOLTIP,
@@ -705,6 +701,8 @@ static gpointer         gtk_widget_parent_class = NULL;
 static guint            widget_signals[LAST_SIGNAL] = { 0 };
 GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR;
 
+static GQuark          quark_accel_path = 0;
+static GQuark          quark_accel_closures = 0;
 static GQuark          quark_pango_context = 0;
 static GQuark          quark_mnemonic_labels = 0;
 static GQuark          quark_tooltip_markup = 0;
@@ -786,29 +784,9 @@ static void
 gtk_widget_base_class_init (gpointer g_class)
 {
   GtkWidgetClass *klass = g_class;
-  GtkWidgetClassPrivate *priv;
-
-  priv = klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
-  
-  priv->template = NULL;
 
-  if (priv->shortcuts == NULL)
-    {
-      priv->shortcuts = g_list_store_new (GTK_TYPE_SHORTCUT);
-    }
-  else
-    {
-      GListModel *parent_shortcuts = G_LIST_MODEL (priv->shortcuts);
-      guint i;
-
-      priv->shortcuts = g_list_store_new (GTK_TYPE_SHORTCUT);
-      for (i = 0; i < g_list_model_get_n_items (parent_shortcuts); i++)
-        {
-          GtkShortcut *shortcut = g_list_model_get_item (parent_shortcuts, i);
-          g_list_store_append (priv->shortcuts, shortcut);
-          g_object_unref (shortcut);
-        }
-    }
+  klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
+  klass->priv->template = NULL;
 }
 
 static void
@@ -861,30 +839,12 @@ gtk_widget_real_grab_notify (GtkWidget *widget,
 static void
 gtk_widget_real_root (GtkWidget *widget)
 {
-  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
-
   gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL);
-
-  for (l = priv->event_controllers; l; l = l->next)
-    {
-      if (GTK_IS_SHORTCUT_CONTROLLER (l->data))
-        gtk_shortcut_controller_root (GTK_SHORTCUT_CONTROLLER (l->data));
-    }
 }
 
 static void
 gtk_widget_real_unroot (GtkWidget *widget)
 {
-  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
-
-  for (l = priv->event_controllers; l; l = l->next)
-    {
-      if (GTK_IS_SHORTCUT_CONTROLLER (l->data))
-        gtk_shortcut_controller_unroot (GTK_SHORTCUT_CONTROLLER (l->data));
-    }
-
   gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
 }
 
@@ -892,10 +852,13 @@ static void
 gtk_widget_class_init (GtkWidgetClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkBindingSet *binding_set;
 
   g_type_class_adjust_private_offset (klass, &GtkWidget_private_offset);
   gtk_widget_parent_class = g_type_class_peek_parent (klass);
 
+  quark_accel_path = g_quark_from_static_string ("gtk-accel-path");
+  quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
   quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
   quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
   quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
@@ -1674,6 +1637,32 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                               G_TYPE_FROM_CLASS (klass),
                               _gtk_marshal_BOOLEAN__INT_INT_BOOLEAN_OBJECTv);
 
+  /**
+   * GtkWidget::popup-menu:
+   * @widget: the object which received the signal
+   *
+   * This signal gets emitted whenever a widget should pop up a context
+   * menu. This usually happens through the standard key binding mechanism;
+   * by pressing a certain key while a widget is focused, the user can cause
+   * the widget to pop up a menu.  For example, the #GtkEntry widget creates
+   * a menu with clipboard commands. See the
+   * [Popup Menu Migration Checklist][checklist-popup-menu]
+   * for an example of how to use this signal.
+   *
+   * Returns: %TRUE if a menu was activated
+   */
+  widget_signals[POPUP_MENU] =
+    g_signal_new (I_("popup-menu"),
+                 G_TYPE_FROM_CLASS (klass),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkWidgetClass, popup_menu),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__VOID,
+                 G_TYPE_BOOLEAN, 0);
+  g_signal_set_va_marshaller (widget_signals[POPUP_MENU],
+                              G_TYPE_FROM_CLASS (klass),
+                              _gtk_marshal_BOOLEAN__VOIDv);
+
   /**
    * GtkWidget::accel-closures-changed:
    * @widget: the object which received the signal.
@@ -1715,6 +1704,12 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                               G_TYPE_FROM_CLASS (klass),
                               _gtk_marshal_BOOLEAN__UINTv);
 
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK,
+                                "popup-menu", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Menu, 0,
+                                "popup-menu", 0);
+
   gtk_widget_class_set_accessible_type (klass, GTK_TYPE_WIDGET_ACCESSIBLE);
   gtk_widget_class_set_css_name (klass, I_("widget"));
 }
@@ -1722,9 +1717,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
 static void
 gtk_widget_base_class_finalize (GtkWidgetClass *klass)
 {
-
   template_data_free (klass->priv->template);
-  g_object_unref (klass->priv->shortcuts);
 }
 
 static void
@@ -2355,7 +2348,6 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
   GtkWidget *widget = GTK_WIDGET (instance);
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
   GType layout_manager_type;
-  GtkEventController *controller;
 
   widget->priv = priv;
 
@@ -2424,19 +2416,9 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
   if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
     priv->root = (GtkRoot *) widget;
 
-  if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_SHORTCUT_MANAGER))
-    gtk_shortcut_manager_create_controllers (widget);
-
   layout_manager_type = gtk_widget_class_get_layout_manager_type (g_class);
   if (layout_manager_type != G_TYPE_INVALID)
     gtk_widget_set_layout_manager (widget, g_object_new (layout_manager_type, NULL));
-
-  if (g_list_model_get_n_items (G_LIST_MODEL (GTK_WIDGET_CLASS (g_class)->priv->shortcuts)) > 0)
-    {
-      controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (GTK_WIDGET_CLASS (g_class)->priv->shortcuts));
-      gtk_event_controller_set_name (controller, "gtk-widget-class-shortcuts");
-      gtk_widget_add_controller (widget, controller);
-    }
 }
 
 /**
@@ -4329,220 +4311,350 @@ gtk_widget_real_size_allocate (GtkWidget *widget,
 {
 }
 
+static gboolean
+gtk_widget_real_can_activate_accel (GtkWidget *widget,
+                                    guint      signal_id)
+{
+  GdkSurface *surface;
+
+  /* widgets must be onscreen for accels to take effect */
+  if (!gtk_widget_is_sensitive (widget) ||
+      !_gtk_widget_get_mapped (widget))
+    return FALSE;
+
+  surface = gtk_widget_get_surface (widget);
+
+  return gdk_surface_is_viewable (surface);
+}
+
 /**
- * gtk_widget_class_add_binding: (skip)
- * @widget_class: the class to add the binding to
- * @keyval: key value of binding to install
- * @mods: key modifier of binding to install
- * @callback: the callback to call upon activation
- * @format_string: GVariant format string for arguments or %NULL for
- *     no arguments
- * @...: arguments, as given by format string.
+ * gtk_widget_can_activate_accel:
+ * @widget: a #GtkWidget
+ * @signal_id: the ID of a signal installed on @widget
  *
- * Creates a new shortcut for @widget_class that calls the given @callback
- * with arguments read according to @format_string.
- * The arguments and format string must be provided in the same way as
- * with g_variant_new().
+ * Determines whether an accelerator that activates the signal
+ * identified by @signal_id can currently be activated.
+ * This is done by emitting the #GtkWidget::can-activate-accel
+ * signal on @widget; if the signal isn’t overridden by a
+ * handler or in a derived widget, then the default check is
+ * that the widget must be sensitive, and the widget and all
+ * its ancestors mapped.
  *
- * This function is a convenience wrapper around
- * gtk_widget_class_add_shortcut() and must be called during class
- * initialization. It does not provide for user_data, if you need that,
- * you will have to use gtk_widget_class_add_shortcut() with a custom
- * shortcut.
+ * Returns: %TRUE if the accelerator can be activated.
  **/
-void
-gtk_widget_class_add_binding (GtkWidgetClass  *widget_class,
-                              guint            keyval,
-                              GdkModifierType  mods,
-                              GtkShortcutFunc  func,
-                              const gchar     *format_string,
-                              ...)
+gboolean
+gtk_widget_can_activate_accel (GtkWidget *widget,
+                               guint      signal_id)
 {
-  GtkShortcut *shortcut;
+  gboolean can_activate = FALSE;
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_signal_emit (widget, widget_signals[CAN_ACTIVATE_ACCEL], 0, signal_id, &can_activate);
+  return can_activate;
+}
 
-  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+typedef struct {
+  GClosure   closure;
+  guint      signal_id;
+} AccelClosure;
+
+static void
+closure_accel_activate (GClosure     *closure,
+                       GValue       *return_value,
+                       guint         n_param_values,
+                       const GValue *param_values,
+                       gpointer      invocation_hint,
+                       gpointer      marshal_data)
+{
+  AccelClosure *aclosure = (AccelClosure*) closure;
+  gboolean can_activate = gtk_widget_can_activate_accel (closure->data, aclosure->signal_id);
+
+  if (can_activate)
+    g_signal_emit (closure->data, aclosure->signal_id, 0);
 
-  shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, mods),
-                               gtk_callback_action_new (func, NULL, NULL));
-  if (format_string)
+  /* whether accelerator was handled */
+  g_value_set_boolean (return_value, can_activate);
+}
+
+static void
+closures_destroy (gpointer data)
+{
+  GSList *slist, *closures = data;
+
+  for (slist = closures; slist; slist = slist->next)
     {
-      va_list args;
-      va_start (args, format_string);
-      gtk_shortcut_set_arguments (shortcut,
-                                  g_variant_new_va (format_string, NULL, &args));
-      va_end (args);
+      g_closure_invalidate (slist->data);
+      g_closure_unref (slist->data);
     }
+  g_slist_free (closures);
+}
 
-  gtk_widget_class_add_shortcut (widget_class, shortcut);
+static GClosure*
+widget_new_accel_closure (GtkWidget *widget,
+                         guint      signal_id)
+{
+  AccelClosure *aclosure;
+  GClosure *closure = NULL;
+  GSList *slist, *closures;
 
-  g_object_unref (shortcut);
+  closures = g_object_steal_qdata (G_OBJECT (widget), quark_accel_closures);
+  for (slist = closures; slist; slist = slist->next)
+    if (!gtk_accel_group_from_accel_closure (slist->data))
+      {
+       /* reuse this closure */
+       closure = slist->data;
+       break;
+      }
+  if (!closure)
+    {
+      closure = g_closure_new_object (sizeof (AccelClosure), G_OBJECT (widget));
+      closures = g_slist_prepend (closures, g_closure_ref (closure));
+      g_closure_sink (closure);
+      g_closure_set_marshal (closure, closure_accel_activate);
+    }
+  g_object_set_qdata_full (G_OBJECT (widget), quark_accel_closures, closures, closures_destroy);
+
+  aclosure = (AccelClosure*) closure;
+  g_assert (closure->data == widget);
+  g_assert (closure->marshal == closure_accel_activate);
+  aclosure->signal_id = signal_id;
+
+  return closure;
 }
 
 /**
- * gtk_widget_class_add_binding_signal: (skip)
- * @widget_class: the class to add the binding to
- * @keyval: key value of binding to install
- * @mods: key modifier of binding to install
- * @signal: the signal to execute
- * @format_string: GVariant format string for arguments or %NULL for
- *     no arguments
- * @...: arguments, as given by format string.
- *
- * Creates a new shortcut for @widget_class that emits the given action
- * @signal with arguments read according to @format_string.
- * The arguments and format string must be provided in the same way as
- * with g_variant_new().
+ * gtk_widget_add_accelerator:
+ * @widget:       widget to install an accelerator on
+ * @accel_signal: widget signal to emit on accelerator activation
+ * @accel_group:  accel group for this widget, added to its toplevel
+ * @accel_key:    GDK keyval of the accelerator
+ * @accel_mods:   modifier key combination of the accelerator
+ * @accel_flags:  flag accelerators, e.g. %GTK_ACCEL_VISIBLE
  *
- * This function is a convenience wrapper around
- * gtk_widget_class_add_shortcut() and must be called during class
- * initialization.
+ * Installs an accelerator for this @widget in @accel_group that causes
+ * @accel_signal to be emitted if the accelerator is activated.
+ * The @accel_group needs to be added to the widget’s toplevel via
+ * gtk_window_add_accel_group(), and the signal must be of type %G_SIGNAL_ACTION.
+ * Accelerators added through this function are not user changeable during
+ * runtime. If you want to support accelerators that can be changed by the
+ * user, use gtk_accel_map_add_entry() and gtk_widget_set_accel_path() or
+ * gtk_menu_item_set_accel_path() instead.
  */
 void
-gtk_widget_class_add_binding_signal (GtkWidgetClass  *widget_class,
-                                     guint            keyval,
-                                     GdkModifierType  mods,
-                                     const gchar     *signal,
-                                     const gchar     *format_string,
-                                     ...)
+gtk_widget_add_accelerator (GtkWidget      *widget,
+                           const gchar    *accel_signal,
+                           GtkAccelGroup  *accel_group,
+                           guint           accel_key,
+                           GdkModifierType accel_mods,
+                           GtkAccelFlags   accel_flags)
 {
-  GtkShortcut *shortcut;
+  GClosure *closure;
+  GSignalQuery query;
 
-  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
-  g_return_if_fail (g_signal_lookup (signal, G_TYPE_FROM_CLASS (widget_class)));
-  /* XXX: validate variant format for signal */
-
-  shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, mods),
-                               gtk_signal_action_new (signal));
-  if (format_string)
-    {
-      va_list args;
-      va_start (args, format_string);
-      gtk_shortcut_set_arguments (shortcut,
-                                  g_variant_new_va (format_string, NULL, &args));
-      va_end (args);
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (accel_signal != NULL);
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
+  if (!query.signal_id ||
+      !(query.signal_flags & G_SIGNAL_ACTION) ||
+      query.return_type != G_TYPE_NONE ||
+      query.n_params)
+    {
+      /* hmm, should be elaborate enough */
+      g_warning (G_STRLOC ": widget '%s' has no activatable signal \"%s\" without arguments",
+                G_OBJECT_TYPE_NAME (widget), accel_signal);
+      return;
     }
 
-  gtk_widget_class_add_shortcut (widget_class, shortcut);
+  closure = widget_new_accel_closure (widget, query.signal_id);
+
+  g_object_ref (widget);
+
+  /* install the accelerator. since we don't map this onto an accel_path,
+   * the accelerator will automatically be locked.
+   */
+  gtk_accel_group_connect (accel_group,
+                          accel_key,
+                          accel_mods,
+                          accel_flags | GTK_ACCEL_LOCKED,
+                          closure);
+
+  g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
 
-  g_object_unref (shortcut);
+  g_object_unref (widget);
 }
 
 /**
- * gtk_widget_class_add_binding_action: (skip)
- * @widget_class: the class to add the binding to
- * @keyval: key value of binding to install
- * @mods: key modifier of binding to install
- * @action_name: the action to activate
- * @format_string: GVariant format string for arguments or %NULL for
- *     no arguments
- * @...: arguments, as given by format string.
+ * gtk_widget_remove_accelerator:
+ * @widget:       widget to install an accelerator on
+ * @accel_group:  accel group for this widget
+ * @accel_key:    GDK keyval of the accelerator
+ * @accel_mods:   modifier key combination of the accelerator
  *
- * Creates a new shortcut for @widget_class that activates the given
- * @action_name with arguments read according to @format_string.
- * The arguments and format string must be provided in the same way as
- * with g_variant_new().
+ * Removes an accelerator from @widget, previously installed with
+ * gtk_widget_add_accelerator().
  *
- * This function is a convenience wrapper around
- * gtk_widget_class_add_shortcut() and must be called during class
- * initialization.
+ * Returns: whether an accelerator was installed and could be removed
  */
-void
-gtk_widget_class_add_binding_action (GtkWidgetClass  *widget_class,
-                                     guint            keyval,
-                                     GdkModifierType  mods,
-                                     const gchar     *action_name,
-                                     const gchar     *format_string,
-                                     ...)
+gboolean
+gtk_widget_remove_accelerator (GtkWidget      *widget,
+                              GtkAccelGroup  *accel_group,
+                              guint           accel_key,
+                              GdkModifierType accel_mods)
 {
-  GtkShortcut *shortcut;
+  GtkAccelGroupEntry *ag_entry;
+  GList *slist, *clist;
+  guint n;
 
-  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
-  /* XXX: validate variant format for action */
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
 
-  shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, mods),
-                               gtk_action_action_new (action_name));
-  if (format_string)
+  ag_entry = gtk_accel_group_query (accel_group, accel_key, accel_mods, &n);
+  clist = gtk_widget_list_accel_closures (widget);
+  for (slist = clist; slist; slist = slist->next)
     {
-      va_list args;
-      va_start (args, format_string);
-      gtk_shortcut_set_arguments (shortcut,
-                                  g_variant_new_va (format_string, NULL, &args));
-      va_end (args);
+      guint i;
+
+      for (i = 0; i < n; i++)
+       if (slist->data == (gpointer) ag_entry[i].closure)
+         {
+           gboolean is_removed = gtk_accel_group_disconnect (accel_group, slist->data);
+
+           g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+
+           g_list_free (clist);
+
+           return is_removed;
+         }
     }
+  g_list_free (clist);
 
-  gtk_widget_class_add_shortcut (widget_class, shortcut);
+  g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)",
+            accel_key, accel_mods, accel_group,
+            G_OBJECT_TYPE_NAME (widget), widget);
 
-  g_object_unref (shortcut);
+  return FALSE;
 }
 
 /**
- * gtk_widget_class_add_shortcut:
- * @widget_class: the class to add the shortcut to
- * @shortcut: (transfer none): the #GtkShortcut to add
- *
- * Installs a shortcut in @widget_class. Every instance created for
- * @widget_class or its subclasses will inherit this shortcut and
- * trigger it.
+ * gtk_widget_list_accel_closures:
+ * @widget:  widget to list accelerator closures for
  *
- * Shortcuts added this way will be triggered in the @GTK_PHASE_BUBBLE
- * phase, which means they may also trigger if child widgets have focus.
+ * Lists the closures used by @widget for accelerator group connections
+ * with gtk_accel_group_connect_by_path() or gtk_accel_group_connect().
+ * The closures can be used to monitor accelerator changes on @widget,
+ * by connecting to the @GtkAccelGroup::accel-changed signal of the
+ * #GtkAccelGroup of a closure which can be found out with
+ * gtk_accel_group_from_accel_closure().
  *
- * This function must only be used in class initialization functions
- * otherwise it is not guaranteed that the shortcut will be installed.
- **/
-void
-gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
-                               GtkShortcut    *shortcut)
+ * Returns: (transfer container) (element-type GClosure):
+ *     a newly allocated #GList of closures
+ */
+GList*
+gtk_widget_list_accel_closures (GtkWidget *widget)
 {
-  GtkWidgetClassPrivate *priv;
-
-  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
-  g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
+  GSList *slist;
+  GList *clist = NULL;
 
-  priv = widget_class->priv;
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
 
-  g_list_store_append (priv->shortcuts, shortcut);
+  for (slist = g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); slist; slist = slist->next)
+    if (gtk_accel_group_from_accel_closure (slist->data))
+      clist = g_list_prepend (clist, slist->data);
+  return clist;
 }
 
-static gboolean
-gtk_widget_real_can_activate_accel (GtkWidget *widget,
-                                    guint      signal_id)
+typedef struct {
+  GQuark         path_quark;
+  GtkAccelGroup *accel_group;
+  GClosure      *closure;
+} AccelPath;
+
+static void
+destroy_accel_path (gpointer data)
 {
-  GdkSurface *surface;
+  AccelPath *apath = data;
 
-  /* widgets must be onscreen for accels to take effect */
-  if (!gtk_widget_is_sensitive (widget) ||
-      !_gtk_widget_get_mapped (widget))
-    return FALSE;
+  gtk_accel_group_disconnect (apath->accel_group, apath->closure);
 
-  surface = gtk_widget_get_surface (widget);
+  /* closures_destroy takes care of unrefing the closure */
+  g_object_unref (apath->accel_group);
 
-  return gdk_surface_is_viewable (surface);
+  g_slice_free (AccelPath, apath);
 }
 
+
 /**
- * gtk_widget_can_activate_accel:
+ * gtk_widget_set_accel_path:
  * @widget: a #GtkWidget
- * @signal_id: the ID of a signal installed on @widget
+ * @accel_path: (allow-none): path used to look up the accelerator
+ * @accel_group: (allow-none): a #GtkAccelGroup.
  *
- * Determines whether an accelerator that activates the signal
- * identified by @signal_id can currently be activated.
- * This is done by emitting the #GtkWidget::can-activate-accel
- * signal on @widget; if the signal isn’t overridden by a
- * handler or in a derived widget, then the default check is
- * that the widget must be sensitive, and the widget and all
- * its ancestors mapped.
+ * Given an accelerator group, @accel_group, and an accelerator path,
+ * @accel_path, sets up an accelerator in @accel_group so whenever the
+ * key binding that is defined for @accel_path is pressed, @widget
+ * will be activated.  This removes any accelerators (for any
+ * accelerator group) installed by previous calls to
+ * gtk_widget_set_accel_path(). Associating accelerators with
+ * paths allows them to be modified by the user and the modifications
+ * to be saved for future use. (See gtk_accel_map_save().)
  *
- * Returns: %TRUE if the accelerator can be activated.
+ * This function is a low level function that would most likely
+ * be used by a menu creation system.
+ *
+ * If you only want to
+ * set up accelerators on menu items gtk_menu_item_set_accel_path()
+ * provides a somewhat more convenient interface.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with
+ * g_intern_static_string().
  **/
-gboolean
-gtk_widget_can_activate_accel (GtkWidget *widget,
-                               guint      signal_id)
+void
+gtk_widget_set_accel_path (GtkWidget     *widget,
+                          const gchar   *accel_path,
+                          GtkAccelGroup *accel_group)
 {
-  gboolean can_activate = FALSE;
-  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-  g_signal_emit (widget, widget_signals[CAN_ACTIVATE_ACCEL], 0, signal_id, &can_activate);
-  return can_activate;
+  AccelPath *apath;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0);
+
+  if (accel_path)
+    {
+      g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+      g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+      gtk_accel_map_add_entry (accel_path, 0, 0);
+      apath = g_slice_new (AccelPath);
+      apath->accel_group = g_object_ref (accel_group);
+      apath->path_quark = g_quark_from_string (accel_path);
+      apath->closure = widget_new_accel_closure (widget, GTK_WIDGET_GET_CLASS (widget)->activate_signal);
+    }
+  else
+    apath = NULL;
+
+  /* also removes possible old settings */
+  g_object_set_qdata_full (G_OBJECT (widget), quark_accel_path, apath, destroy_accel_path);
+
+  if (apath)
+    gtk_accel_group_connect_by_path (apath->accel_group, g_quark_to_string (apath->path_quark), apath->closure);
+
+  g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+}
+
+const gchar*
+_gtk_widget_get_accel_path (GtkWidget *widget,
+                           gboolean  *locked)
+{
+  AccelPath *apath;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path);
+  if (locked)
+    *locked = apath ? gtk_accel_group_get_is_locked (apath->accel_group) : TRUE;
+  return apath ? g_quark_to_string (apath->path_quark) : NULL;
 }
 
 /**
@@ -4798,6 +4910,11 @@ gtk_widget_event (GtkWidget *widget,
   if (return_val == FALSE)
     return_val |= gtk_widget_run_controllers (widget, event, target, x, y, GTK_PHASE_BUBBLE);
 
+  if (return_val == FALSE &&
+      (gdk_event_get_event_type (event) == GDK_KEY_PRESS ||
+       gdk_event_get_event_type (event) == GDK_KEY_RELEASE))
+    return_val |= gtk_bindings_activate_event (G_OBJECT (widget), event);
+
   return return_val;
 }
 
@@ -7440,6 +7557,10 @@ gtk_widget_real_destroy (GtkWidget *object)
       priv->accessible = NULL;
     }
 
+  /* wipe accelerator closures (keep order) */
+  g_object_set_qdata (G_OBJECT (widget), quark_accel_path, NULL);
+  g_object_set_qdata (G_OBJECT (widget), quark_accel_closures, NULL);
+
   /* Callers of add_mnemonic_label() should disconnect on ::destroy */
   g_object_set_qdata (G_OBJECT (widget), quark_mnemonic_labels, NULL);
 
@@ -8875,6 +8996,90 @@ static const GtkBuildableParser accessibility_parser =
     accessibility_text,
   };
 
+typedef struct
+{
+  GObject *object;
+  GtkBuilder *builder;
+  guint    key;
+  guint    modifiers;
+  gchar   *signal;
+} AccelGroupParserData;
+
+static void
+accel_group_start_element (GtkBuildableParseContext  *context,
+                           const gchar               *element_name,
+                           const gchar              **names,
+                           const gchar              **values,
+                           gpointer                   user_data,
+                           GError                   **error)
+{
+  AccelGroupParserData *data = (AccelGroupParserData*)user_data;
+
+  if (strcmp (element_name, "accelerator") == 0)
+    {
+      const gchar *key_str = NULL;
+      const gchar *signal = NULL;
+      const gchar *modifiers_str = NULL;
+      guint key = 0;
+      guint modifiers = 0;
+
+      if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+        return;
+
+      if (!g_markup_collect_attributes (element_name, names, values, error,
+                                        G_MARKUP_COLLECT_STRING, "key", &key_str,
+                                        G_MARKUP_COLLECT_STRING, "signal", &signal,
+                                        G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "modifiers", &modifiers_str,
+                                        G_MARKUP_COLLECT_INVALID))
+        {
+          _gtk_builder_prefix_error (data->builder, context, error);
+          return;
+        }
+
+      key = gdk_keyval_from_name (key_str);
+      if (key == 0)
+        {
+          g_set_error (error,
+                       GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
+                       "Could not parse key '%s'", key_str);
+          _gtk_builder_prefix_error (data->builder, context, error);
+          return;
+        }
+
+      if (modifiers_str != NULL)
+        {
+          GFlagsValue aliases[2] = {
+            { 0, "primary", "primary" },
+            { 0, NULL, NULL }
+          };
+
+          aliases[0].value = _gtk_get_primary_accel_mod ();
+
+          if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, aliases,
+                                               modifiers_str, &modifiers, error))
+            {
+              _gtk_builder_prefix_error (data->builder, context, error);
+             return;
+            }
+        }
+
+      data->key = key;
+      data->modifiers = modifiers;
+      data->signal = g_strdup (signal);
+    }
+  else
+    {
+      _gtk_builder_error_unhandled_tag (data->builder, context,
+                                        "GtkWidget", element_name,
+                                        error);
+    }
+}
+
+static const GtkBuildableParser accel_group_parser =
+  {
+    accel_group_start_element,
+  };
+
 typedef struct
 {
   GtkBuilder *builder;
@@ -9078,6 +9283,20 @@ gtk_widget_buildable_custom_tag_start (GtkBuildable       *buildable,
                                        GtkBuildableParser *parser,
                                        gpointer           *parser_data)
 {
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      AccelGroupParserData *data;
+
+      data = g_slice_new0 (AccelGroupParserData);
+      data->object = (GObject *)g_object_ref (buildable);
+      data->builder = builder;
+
+      *parser = accel_group_parser;
+      *parser_data = data;
+
+      return TRUE;
+    }
+
   if (strcmp (tagname, "accessibility") == 0)
     {
       AccessibilitySubParserData *data;
@@ -9130,6 +9349,45 @@ gtk_widget_buildable_custom_tag_end (GtkBuildable  *buildable,
 {
 }
 
+void
+_gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
+                                          GtkWidget *toplevel,
+                                          gpointer   user_data)
+{
+  AccelGroupParserData *accel_data;
+  GSList *accel_groups;
+  GtkAccelGroup *accel_group;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_WIDGET (toplevel));
+  g_return_if_fail (user_data != NULL);
+
+  accel_data = (AccelGroupParserData*)user_data;
+  accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
+  if (g_slist_length (accel_groups) == 0)
+    {
+      accel_group = gtk_accel_group_new ();
+      if (GTK_IS_WINDOW (toplevel))
+        gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
+    }
+  else
+    {
+      g_assert (g_slist_length (accel_groups) == 1);
+      accel_group = g_slist_nth_data (accel_groups, 0);
+    }
+
+  gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object),
+                             accel_data->signal,
+                             accel_group,
+                             accel_data->key,
+                             accel_data->modifiers,
+                             GTK_ACCEL_VISIBLE);
+
+  g_object_unref (accel_data->object);
+  g_free (accel_data->signal);
+  g_slice_free (AccelGroupParserData, accel_data);
+}
+
 static void
 gtk_widget_buildable_finish_layout_properties (GtkWidget *widget,
                                                GtkWidget *parent,
@@ -9203,7 +9461,19 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
                                       const gchar  *tagname,
                                       gpointer      user_data)
 {
-  if (strcmp (tagname, "accessibility") == 0)
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      AccelGroupParserData *accel_data;
+      GtkRoot *root;
+
+      accel_data = (AccelGroupParserData*)user_data;
+      g_assert (accel_data->object);
+
+      root = _gtk_widget_get_root (GTK_WIDGET (accel_data->object));
+
+      _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), GTK_WIDGET (root), user_data);
+    }
+  else if (strcmp (tagname, "accessibility") == 0)
     {
       AccessibilitySubParserData *a11y_data;
 
@@ -11583,24 +11853,6 @@ gtk_widget_reset_controllers (GtkWidget *widget)
     }
 }
 
-GList *
-gtk_widget_list_controllers (GtkWidget           *widget,
-                             GtkPropagationPhase  phase)
-{
-  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *res = NULL, *l;
-
-  for (l = priv->event_controllers; l; l = l->next)
-    {
-      GtkEventController *controller = l->data;
-
-      if (gtk_event_controller_get_propagation_phase (controller) == phase)
-        res = g_list_prepend (res, controller);
-    }
-
-  return g_list_reverse (res);
-}
-
 static inline void
 gtk_widget_maybe_add_debug_render_nodes (GtkWidget   *widget,
                                          GtkSnapshot *snapshot)
index d9becfab1797fe2a1da05c8bb472fb4a82528390..9121d5bb7ea72e5613dd85d5db9d9608095a6e59 100644 (file)
@@ -33,8 +33,6 @@
 #include <gsk/gsk.h>
 #include <gtk/gtkaccelgroup.h>
 #include <gtk/gtkborder.h>
-#include <gtk/gtkshortcut.h>
-#include <gtk/gtkshortcutaction.h>
 #include <gtk/gtktypes.h>
 #include <atk/atk.h>
 
@@ -376,32 +374,23 @@ GDK_AVAILABLE_IN_ALL
 GType                   gtk_widget_class_get_layout_manager_type        (GtkWidgetClass *widget_class);
 
 GDK_AVAILABLE_IN_ALL
-void       gtk_widget_class_add_binding   (GtkWidgetClass      *widget_class,
-                                           guint                keyval,
-                                           GdkModifierType      mods,
-                                           GtkShortcutFunc      callback,
-                                           const gchar         *format_string,
-                                           ...);
+void       gtk_widget_add_accelerator     (GtkWidget           *widget,
+                                           const gchar         *accel_signal,
+                                           GtkAccelGroup       *accel_group,
+                                           guint                accel_key,
+                                           GdkModifierType      accel_mods,
+                                           GtkAccelFlags        accel_flags);
 GDK_AVAILABLE_IN_ALL
-void       gtk_widget_class_add_binding_signal
-                                          (GtkWidgetClass      *widget_class,
-                                           GdkModifierType      mods,
-                                           guint                keyval,
-                                           const gchar         *signal,
-                                           const gchar         *format_string,
-                                           ...);
+gboolean   gtk_widget_remove_accelerator  (GtkWidget           *widget,
+                                           GtkAccelGroup       *accel_group,
+                                           guint                accel_key,
+                                           GdkModifierType      accel_mods);
 GDK_AVAILABLE_IN_ALL
-void       gtk_widget_class_add_binding_action
-                                          (GtkWidgetClass      *widget_class,
-                                           GdkModifierType      mods,
-                                           guint                keyval,
-                                           const gchar         *action_name,
-                                           const gchar         *format_string,
-                                           ...);
+void       gtk_widget_set_accel_path      (GtkWidget           *widget,
+                                           const gchar         *accel_path,
+                                           GtkAccelGroup       *accel_group);
 GDK_AVAILABLE_IN_ALL
-void       gtk_widget_class_add_shortcut  (GtkWidgetClass      *widget_class,
-                                           GtkShortcut         *shortcut);
-
+GList*     gtk_widget_list_accel_closures (GtkWidget           *widget);
 GDK_AVAILABLE_IN_ALL
 gboolean   gtk_widget_can_activate_accel  (GtkWidget           *widget,
                                            guint                signal_id);
index 82943b5eb52cd3b61fcf81b235385f89030fb455..1018c9c915d0afa867f18f58a35e91c89a2ce758 100644 (file)
@@ -230,6 +230,9 @@ void         _gtk_widget_add_attached_window    (GtkWidget    *widget,
 void         _gtk_widget_remove_attached_window (GtkWidget    *widget,
                                                  GtkWindow    *window);
 
+const gchar*      _gtk_widget_get_accel_path               (GtkWidget *widget,
+                                                            gboolean  *locked);
+
 AtkObject *       _gtk_widget_peek_accessible              (GtkWidget *widget);
 
 void              _gtk_widget_set_has_default              (GtkWidget *widget,
@@ -255,6 +258,9 @@ void              _gtk_widget_synthesize_crossing          (GtkWidget       *fro
                                                             GdkDevice       *device,
                                                             GdkCrossingMode  mode);
 
+void              _gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
+                                                            GtkWidget *toplevel,
+                                                            gpointer   user_data);
 GtkStyleContext * _gtk_widget_peek_style_context           (GtkWidget *widget);
 
 gboolean          _gtk_widget_captured_event               (GtkWidget *widget,
@@ -277,9 +283,6 @@ gboolean          gtk_widget_has_size_request              (GtkWidget *widget);
 
 void              gtk_widget_reset_controllers             (GtkWidget *widget);
 
-GList *           gtk_widget_list_controllers              (GtkWidget           *widget,
-                                                            GtkPropagationPhase  phase);
-
 gboolean          gtk_widget_query_tooltip                 (GtkWidget  *widget,
                                                             gint        x,
                                                             gint        y,
index be93fa6e9089c52f15cda1699418c05f92d5f040..3549009b2e61bd64a3e2d211ce95ad7ffa5f8a21 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "gtkaccelgroupprivate.h"
 #include "gtkapplicationprivate.h"
+#include "gtkbindings.h"
 #include "gtkbox.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
@@ -53,6 +54,7 @@
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkmessagedialog.h"
+#include "gtkmnemonichash.h"
 #include "gtkpointerfocusprivate.h"
 #include "gtkpopovermenuprivate.h"
 #include "gtkmodelbuttonprivate.h"
 #include "gtkroot.h"
 #include "gtknative.h"
 #include "gtksettings.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcutmanager.h"
-#include "gtkshortcuttrigger.h"
 #include "gtksnapshot.h"
 #include "gtkstylecontextprivate.h"
 #include "gtktypebuiltins.h"
  * widget that is added as a titlebar child.
  */
 
-#define MENU_BAR_ACCEL GDK_KEY_F10
+#define MENU_BAR_ACCEL "F10"
 #define RESIZE_HANDLE_SIZE 20
 #define MNEMONICS_DELAY 300 /* ms */
 #define NO_CONTENT_CHILD_NAT 200
@@ -185,6 +183,8 @@ struct _GtkWindowPopover
 
 typedef struct
 {
+  GtkMnemonicHash       *mnemonic_hash;
+
   GtkWidget             *attach_widget;
   GtkWidget             *default_widget;
   GtkWidget             *initial_focus;
@@ -197,6 +197,8 @@ typedef struct
 
   GQueue                 popovers;
 
+  GdkModifierType        mnemonic_modifier;
+
   gchar   *startup_id;
   gchar   *title;
 
@@ -260,7 +262,6 @@ typedef struct
   GtkGesture *drag_gesture;
   GtkGesture *bubble_drag_gesture;
   GtkEventController *key_controller;
-  GtkEventController *application_shortcut_controller;
 
   GtkCssNode *decoration_node;
 
@@ -470,9 +471,6 @@ static void     update_window_buttons                 (GtkWindow    *window);
 static void     get_shadow_width                      (GtkWindow    *window,
                                                        GtkBorder    *shadow_width);
 
-static gboolean    gtk_window_activate_menubar        (GtkWidget    *widget,
-                                                       GVariant     *args,
-                                                       gpointer      unused);
 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
 static void        gtk_window_free_key_hash       (GtkWindow   *window);
 #ifdef GDK_WINDOWING_X11
@@ -507,6 +505,7 @@ static gboolean     disable_startup_notification = FALSE;
 
 static GQuark       quark_gtk_window_key_hash = 0;
 static GQuark       quark_gtk_window_icon_info = 0;
+static GQuark       quark_gtk_buildable_accels = 0;
 
 static GtkBuildableIface *parent_buildable_iface;
 
@@ -529,8 +528,20 @@ static void     gtk_window_buildable_set_buildable_property (GtkBuildable
                                                              GtkBuilder         *builder,
                                                              const gchar        *name,
                                                              const GValue       *value);
+static void     gtk_window_buildable_parser_finished        (GtkBuildable       *buildable,
+                                                             GtkBuilder         *builder);
+static gboolean gtk_window_buildable_custom_tag_start       (GtkBuildable       *buildable,
+                                                             GtkBuilder         *builder,
+                                                             GObject            *child,
+                                                             const gchar        *tagname,
+                                                             GtkBuildableParser *parser,
+                                                             gpointer           *data);
+static void     gtk_window_buildable_custom_finished        (GtkBuildable       *buildable,
+                                                             GtkBuilder         *builder,
+                                                             GObject            *child,
+                                                             const gchar        *tagname,
+                                                             gpointer            user_data);
 
-static void             gtk_window_shortcut_manager_interface_init      (GtkShortcutManagerInterface *iface);
 /* GtkRoot */
 static void             gtk_window_root_interface_init (GtkRootInterface *iface);
 static void             gtk_window_native_interface_init  (GtkNativeInterface  *iface);
@@ -551,52 +562,41 @@ G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
                                                gtk_window_buildable_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
                                                gtk_window_native_interface_init)
-                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SHORTCUT_MANAGER,
-                                               gtk_window_shortcut_manager_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
                                                gtk_window_root_interface_init))
 
 static void
-add_tab_bindings (GtkWidgetClass   *widget_class,
+add_tab_bindings (GtkBindingSet    *binding_set,
                  GdkModifierType   modifiers,
                  GtkDirectionType  direction)
 {
-  GtkShortcut *shortcut;
-
-  shortcut = gtk_shortcut_new_with_arguments (
-                 gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_Tab, modifiers),
-                                              gtk_keyval_trigger_new (GDK_KEY_KP_Tab, modifiers)),
-                 gtk_signal_action_new ("move-focus"),
-                 "(i)", direction);
-
-  gtk_widget_class_add_shortcut (widget_class, shortcut);
-
-  g_object_unref (shortcut);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static void
-add_arrow_bindings (GtkWidgetClass   *widget_class,
+add_arrow_bindings (GtkBindingSet    *binding_set,
                    guint             keysym,
                    GtkDirectionType  direction)
 {
   guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
   
-  gtk_widget_class_add_binding_signal (widget_class, keysym, 0,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class, keysym, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, 0,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
-  gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, GDK_CONTROL_MASK,
-                                       "move-focus",
-                                       "(i)",
-                                       direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, 0,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
+  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+                                "move-focus", 1,
+                                GTK_TYPE_DIRECTION_TYPE, direction);
 }
 
 static guint32
@@ -757,11 +757,16 @@ static void
 gtk_window_class_init (GtkWindowClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+  GtkBindingSet *binding_set;
 
+  widget_class = (GtkWidgetClass*) klass;
+  container_class = (GtkContainerClass*) klass;
+  
   quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
   quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
+  quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
 
   if (toplevel_list == NULL)
     toplevel_list = g_list_store_new (GTK_TYPE_WIDGET);
@@ -1100,32 +1105,36 @@ gtk_window_class_init (GtkWindowClass *klass)
   gtk_widget_class_install_action (widget_class, "default.activate", NULL,
                                    gtk_window_activate_default_activate);
 
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0,
-                                       "activate-focus", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0,
-                                       "activate-focus", NULL);
+  binding_set = gtk_binding_set_by_class (klass);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+                                "activate-focus", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+                                "activate-focus", 0);
   
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
-                                       "activate-default", NULL);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
-                                       "activate-default", NULL);
-
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_I, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
-                                       "enable-debugging", "(b)", FALSE);
-  gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_D, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
-                                       "enable-debugging", "(b)", TRUE);
-
-  add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
-  add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
-  add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
-  add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
-  add_tab_bindings (widget_class, 0, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
-  add_tab_bindings (widget_class, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-  add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+                                "activate-default", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+                                "activate-default", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_I, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+                                "enable-debugging", 1,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_D, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+                                "enable-debugging", 1,
+                                G_TYPE_BOOLEAN, TRUE);
+
+  add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+  add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+  add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+  add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+  add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+  add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_FRAME);
@@ -1716,9 +1725,9 @@ gtk_window_init (GtkWindow *window)
   GtkWidget *widget;
   GtkCssNode *widget_node;
   GdkSeat *seat;
+  GtkEventController *motion_controller;
   GtkEventController *controller;
   GtkDropTargetAsync *target;
-  GtkShortcut *shortcut;
 
   widget = GTK_WIDGET (window);
 
@@ -1733,6 +1742,7 @@ gtk_window_init (GtkWindow *window)
   priv->modal = FALSE;
   priv->gravity = GDK_GRAVITY_NORTH_WEST;
   priv->decorated = TRUE;
+  priv->mnemonic_modifier = GDK_MOD1_MASK;
   priv->display = gdk_display_get_default ();
 
   priv->state = GDK_SURFACE_STATE_WITHDRAWN;
@@ -1774,12 +1784,12 @@ gtk_window_init (GtkWindow *window)
   g_signal_connect (seat, "device-removed",
                     G_CALLBACK (device_removed_cb), window);
 
-  controller = gtk_event_controller_motion_new ();
-  gtk_event_controller_set_propagation_phase (controller,
+  motion_controller = gtk_event_controller_motion_new ();
+  gtk_event_controller_set_propagation_phase (motion_controller,
                                               GTK_PHASE_CAPTURE);
-  g_signal_connect_swapped (controller, "motion",
+  g_signal_connect_swapped (motion_controller, "motion",
                             G_CALLBACK (gtk_window_capture_motion), window);
-  gtk_widget_add_controller (widget, controller);
+  gtk_widget_add_controller (widget, motion_controller);
 
   priv->key_controller = gtk_event_controller_key_new ();
   gtk_event_controller_set_propagation_phase (priv->key_controller, GTK_PHASE_CAPTURE);
@@ -1797,15 +1807,6 @@ gtk_window_init (GtkWindow *window)
 
   /* Shared constraint solver */
   priv->constraint_solver = gtk_constraint_solver_new ();
-
-  controller = gtk_shortcut_controller_new ();
-  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
-
-  shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (MENU_BAR_ACCEL, 0),
-                               gtk_callback_action_new (gtk_window_activate_menubar, NULL, NULL));
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  gtk_event_controller_set_name (controller, "gtk-window-menubar-accel");
-  gtk_widget_add_controller (widget, controller);
 }
 
 static GtkGesture *
@@ -2013,6 +2014,9 @@ gtk_window_buildable_interface_init (GtkBuildableIface *iface)
 {
   parent_buildable_iface = g_type_interface_peek_parent (iface);
   iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
+  iface->parser_finished = gtk_window_buildable_parser_finished;
+  iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
+  iface->custom_finished = gtk_window_buildable_custom_finished;
   iface->add_child = gtk_window_buildable_add_child;
 }
 
@@ -2045,9 +2049,166 @@ gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
     g_object_set_property (G_OBJECT (buildable), name, value);
 }
 
+typedef struct {
+  gchar *name;
+  gint line;
+  gint col;
+} ItemData;
+
+static void
+item_data_free (gpointer data)
+{
+  ItemData *item_data = data;
+
+  g_free (item_data->name);
+  g_free (item_data);
+}
+
+static void
+item_list_free (gpointer data)
+{
+  GSList *list = data;
+
+  g_slist_free_full (list, item_data_free);
+}
+
+static void
+gtk_window_buildable_parser_finished (GtkBuildable *buildable,
+                                     GtkBuilder   *builder)
+{
+  GtkWindow *window = GTK_WINDOW (buildable);
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GObject *object;
+  GSList *accels, *l;
+
+  if (priv->builder_visible)
+    gtk_widget_show (GTK_WIDGET (buildable));
+
+  accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
+  for (l = accels; l; l = l->next)
+    {
+      ItemData *data = l->data;
+
+      object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col);
+      if (!object)
+       continue;
+      gtk_window_add_accel_group (GTK_WINDOW (buildable), GTK_ACCEL_GROUP (object));
+    }
+
+  g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
+
+  parent_buildable_iface->parser_finished (buildable, builder);
+}
+
+typedef struct {
+  GObject *object;
+  GtkBuilder *builder;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+window_start_element (GtkBuildableParseContext  *context,
+                      const gchar          *element_name,
+                      const gchar         **names,
+                      const gchar         **values,
+                      gpointer              user_data,
+                      GError              **error)
+{
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  if (strcmp (element_name, "group") == 0)
+    {
+      const gchar *name;
+      ItemData *item_data;
+
+      if (!_gtk_builder_check_parent (data->builder, context, "accel-groups", error))
+        return;
+
+      if (!g_markup_collect_attributes (element_name, names, values, error,
+                                        G_MARKUP_COLLECT_STRING, "name", &name,
+                                        G_MARKUP_COLLECT_INVALID))
+        {
+          _gtk_builder_prefix_error (data->builder, context, error);
+          return;
+        }
+
+      item_data = g_new (ItemData, 1);
+      item_data->name = g_strdup (name);
+      gtk_buildable_parse_context_get_position (context, &item_data->line, &item_data->col);
+      data->items = g_slist_prepend (data->items, item_data);
+    }
+  else if (strcmp (element_name, "accel-groups") == 0)
+    {
+      if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+        return;
+
+      if (!g_markup_collect_attributes (element_name, names, values, error,
+                                        G_MARKUP_COLLECT_INVALID, NULL, NULL,
+                                        G_MARKUP_COLLECT_INVALID))
+        _gtk_builder_prefix_error (data->builder, context, error);
+    }
+  else
+    {
+      _gtk_builder_error_unhandled_tag (data->builder, context,
+                                        "GtkWindow", element_name,
+                                        error);
+    }
+}
+
+static const GtkBuildableParser window_parser =
+  {
+    window_start_element
+  };
+
+static gboolean
+gtk_window_buildable_custom_tag_start (GtkBuildable       *buildable,
+                                       GtkBuilder         *builder,
+                                       GObject            *child,
+                                       const gchar        *tagname,
+                                       GtkBuildableParser *parser,
+                                       gpointer           *parser_data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, parser_data))
+    return TRUE;
+
+  if (strcmp (tagname, "accel-groups") == 0)
+    {
+      GSListSubParserData *data;
+
+      data = g_slice_new0 (GSListSubParserData);
+      data->items = NULL;
+      data->object = G_OBJECT (buildable);
+      data->builder = builder;
+
+      *parser = window_parser;
+      *parser_data = data;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 static void
-gtk_window_shortcut_manager_interface_init (GtkShortcutManagerInterface *iface)
+gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
+                                      GtkBuilder    *builder,
+                                      GObject       *child,
+                                      const gchar   *tagname,
+                                      gpointer       user_data)
 {
+  parent_buildable_iface->custom_finished (buildable, builder, child,
+                                          tagname, user_data);
+
+  if (strcmp (tagname, "accel-groups") == 0)
+    {
+      GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+      g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
+                               data->items, (GDestroyNotify) item_list_free);
+
+      g_slice_free (GSListSubParserData, data);
+    }
 }
 
 static GdkDisplay *
@@ -2381,6 +2542,174 @@ _gtk_window_notify_keys_changed (GtkWindow *window)
     }
 }
 
+/**
+ * gtk_window_add_accel_group:
+ * @window: window to attach accelerator group to
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Associate @accel_group with @window, such that calling
+ * gtk_accel_groups_activate() on @window will activate accelerators
+ * in @accel_group.
+ **/
+void
+gtk_window_add_accel_group (GtkWindow     *window,
+                           GtkAccelGroup *accel_group)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  _gtk_accel_group_attach (accel_group, G_OBJECT (window));
+  g_signal_connect_object (accel_group, "accel-changed",
+                          G_CALLBACK (_gtk_window_notify_keys_changed),
+                          window, G_CONNECT_SWAPPED);
+  _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_remove_accel_group:
+ * @window: a #GtkWindow
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Reverses the effects of gtk_window_add_accel_group().
+ **/
+void
+gtk_window_remove_accel_group (GtkWindow     *window,
+                              GtkAccelGroup *accel_group)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+  g_signal_handlers_disconnect_by_func (accel_group,
+                                       _gtk_window_notify_keys_changed,
+                                       window);
+  _gtk_accel_group_detach (accel_group, G_OBJECT (window));
+  _gtk_window_notify_keys_changed (window);
+}
+
+static GtkMnemonicHash *
+gtk_window_get_mnemonic_hash (GtkWindow *window,
+                             gboolean   create)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  if (!priv->mnemonic_hash && create)
+    priv->mnemonic_hash = _gtk_mnemonic_hash_new ();
+
+  return priv->mnemonic_hash;
+}
+
+/**
+ * gtk_window_add_mnemonic:
+ * @window: a #GtkWindow
+ * @keyval: the mnemonic
+ * @target: the widget that gets activated by the mnemonic
+ *
+ * Adds a mnemonic to this window.
+ */
+void
+gtk_window_add_mnemonic (GtkWindow *window,
+                        guint      keyval,
+                        GtkWidget *target)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (GTK_IS_WIDGET (target));
+
+  _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
+                         keyval, target);
+  _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_remove_mnemonic:
+ * @window: a #GtkWindow
+ * @keyval: the mnemonic
+ * @target: the widget that gets activated by the mnemonic
+ *
+ * Removes a mnemonic from this window.
+ */
+void
+gtk_window_remove_mnemonic (GtkWindow *window,
+                           guint      keyval,
+                           GtkWidget *target)
+{
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (GTK_IS_WIDGET (target));
+  
+  _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
+                            keyval, target);
+  _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_mnemonic_activate:
+ * @window: a #GtkWindow
+ * @keyval: the mnemonic
+ * @modifier: the modifiers
+ *
+ * Activates the targets associated with the mnemonic.
+ *
+ * Returns: %TRUE if the activation is done.
+ */
+gboolean
+gtk_window_mnemonic_activate (GtkWindow      *window,
+                             guint           keyval,
+                             GdkModifierType modifier)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
+      {
+       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+       if (mnemonic_hash)
+         return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
+      }
+
+  return FALSE;
+}
+
+/**
+ * gtk_window_set_mnemonic_modifier:
+ * @window: a #GtkWindow
+ * @modifier: the modifier mask used to activate
+ *               mnemonics on this window.
+ *
+ * Sets the mnemonic modifier for this window. 
+ **/
+void
+gtk_window_set_mnemonic_modifier (GtkWindow      *window,
+                                 GdkModifierType modifier)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
+
+  priv->mnemonic_modifier = modifier;
+  _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_get_mnemonic_modifier:
+ * @window: a #GtkWindow
+ *
+ * Returns the mnemonic modifier for this window. See
+ * gtk_window_set_mnemonic_modifier().
+ *
+ * Returns: the modifier mask used to activate
+ *               mnemonics on this window.
+ **/
+GdkModifierType
+gtk_window_get_mnemonic_modifier (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
+
+  return priv->mnemonic_modifier;
+}
+
 /**
  * gtk_window_get_focus:
  * @window: a #GtkWindow
@@ -2796,9 +3125,6 @@ gtk_window_release_application (GtkWindow *window)
       /* steal reference into temp variable */
       application = priv->application;
       priv->application = NULL;
-      gtk_widget_remove_controller (GTK_WIDGET (window),
-                                    priv->application_shortcut_controller);
-      priv->application_shortcut_controller = NULL;
 
       gtk_application_remove_window (application, window);
       g_object_unref (application);
@@ -2839,18 +3165,9 @@ gtk_window_set_application (GtkWindow      *window,
 
       if (priv->application != NULL)
         {
-          GtkApplicationAccels *app_accels;
-
           g_object_ref (priv->application);
 
           gtk_application_add_window (priv->application, window);
-
-          app_accels = gtk_application_get_application_accels (priv->application);
-          priv->application_shortcut_controller = gtk_shortcut_controller_new_for_model (gtk_application_accels_get_shortcuts (app_accels));
-          gtk_event_controller_set_name (priv->application_shortcut_controller, "gtk-application-shortcuts");
-          gtk_event_controller_set_propagation_phase (priv->application_shortcut_controller, GTK_PHASE_CAPTURE);
-          gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (priv->application_shortcut_controller), GTK_SHORTCUT_SCOPE_GLOBAL);
-          gtk_widget_add_controller (GTK_WIDGET (window), priv->application_shortcut_controller);
         }
 
       _gtk_widget_update_parent_muxer (GTK_WIDGET (window));
@@ -4037,11 +4354,16 @@ gtk_window_finalize (GObject *object)
 {
   GtkWindow *window = GTK_WINDOW (object);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GtkMnemonicHash *mnemonic_hash;
 
   g_clear_pointer (&priv->extra_input_region, cairo_region_destroy);
   g_free (priv->title);
   gtk_window_release_application (window);
 
+  mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+  if (mnemonic_hash)
+    _gtk_mnemonic_hash_free (mnemonic_hash);
+
   if (priv->geometry_info)
     {
       g_free (priv->geometry_info);
@@ -5360,6 +5682,8 @@ _gtk_window_query_nonaccels (GtkWindow      *window,
                             guint           accel_key,
                             GdkModifierType accel_mods)
 {
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
 
   /* movement keys are considered locked accels */
@@ -5376,9 +5700,77 @@ _gtk_window_query_nonaccels (GtkWindow      *window,
          return TRUE;
     }
 
+  /* mnemonics are considered locked accels */
+  if (accel_mods == priv->mnemonic_modifier)
+    {
+      GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+      if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
+       return TRUE;
+    }
+
   return FALSE;
 }
 
+/**
+ * gtk_window_propagate_key_event:
+ * @window:  a #GtkWindow
+ * @event:   a #GdkEvent
+ *
+ * Propagate a key press or release event to the focus widget and
+ * up the focus container chain until a widget handles @event.
+ * This is normally called by the default ::key_press_event and
+ * ::key_release_event handlers for toplevel windows,
+ * however in some cases it may be useful to call this directly when
+ * overriding the standard key handling for a toplevel window.
+ *
+ * Returns: %TRUE if a widget in the focus chain handled the event.
+ */
+gboolean
+gtk_window_propagate_key_event (GtkWindow *window,
+                                GdkEvent  *event)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  gboolean handled = FALSE;
+  GtkWidget *widget, *focus, *target;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  widget = GTK_WIDGET (window);
+
+  focus = priv->focus_widget;
+  if (focus)
+    g_object_ref (focus);
+  
+  target = focus;
+
+  while (!handled &&
+         focus && focus != widget &&
+         gtk_widget_get_root (focus) == GTK_ROOT (widget))
+    {
+      GtkWidget *parent;
+      
+      if (gtk_widget_is_sensitive (focus))
+        {
+          handled = gtk_widget_event (focus, (GdkEvent *)event, target);
+          if (handled)
+            break;
+        }
+
+      parent = _gtk_widget_get_parent (focus);
+      if (parent)
+        g_object_ref (parent);
+      
+      g_object_unref (focus);
+      
+      focus = parent;
+    }
+  
+  if (focus)
+    g_object_unref (focus);
+
+  return handled;
+}
+
 static GtkWindowRegion
 get_active_region_type (GtkWindow *window, gint x, gint y)
 {
@@ -5424,6 +5816,9 @@ gtk_window_has_mnemonic_modifier_pressed (GtkWindow *window)
   GList *seats, *s;
   gboolean retval = FALSE;
 
+  if (!priv->mnemonic_modifier)
+    return FALSE;
+
   seats = gdk_display_list_seats (gtk_widget_get_display (GTK_WIDGET (window)));
 
   for (s = seats; s; s = s->next)
@@ -5432,7 +5827,7 @@ gtk_window_has_mnemonic_modifier_pressed (GtkWindow *window)
       GdkModifierType mask;
 
       gdk_device_get_state (dev, priv->surface, NULL, &mask);
-      if ((mask & gtk_accelerator_get_default_mod_mask ()) == GDK_MOD1_MASK)
+      if (priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
         {
           retval = TRUE;
           break;
@@ -7378,42 +7773,130 @@ _gtk_window_set_window_group (GtkWindow      *window,
 }
 
 static gboolean
-gtk_window_activate_menubar (GtkWidget *widget,
-                             GVariant  *args,
-                             gpointer   unused)
+gtk_window_activate_menubar (GtkWindow *window,
+                             GdkEvent  *event)
 {
-  GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GList *tmp_menubars, *l;
-  GPtrArray *menubars;
-  GtkWidget *focus;
-  GtkWidget *first;
+  guint keyval = 0;
+  GdkModifierType mods = 0;
 
-  focus = gtk_window_get_focus (window);
+  gtk_accelerator_parse (MENU_BAR_ACCEL, &keyval, &mods);
 
-  if (priv->title_box != NULL &&
-      (focus == NULL || !gtk_widget_is_ancestor (focus, priv->title_box)) &&
-      gtk_widget_child_focus (priv->title_box, GTK_DIR_TAB_FORWARD))
-    return TRUE;
+  if (keyval == 0)
+    {
+      g_warning ("Failed to parse menu bar accelerator '%s'", MENU_BAR_ACCEL);
+      return FALSE;
+    }
 
-  tmp_menubars = gtk_popover_menu_bar_get_viewable_menu_bars (window);
-  if (tmp_menubars == NULL)
+  if (!(gdk_event_get_event_type (event) == GDK_KEY_PRESS ||
+        gdk_event_get_event_type (event) == GDK_KEY_RELEASE))
     return FALSE;
 
-  menubars = g_ptr_array_sized_new (g_list_length (tmp_menubars));;
-  for (l = tmp_menubars; l; l = l->next)
-    g_ptr_array_add (menubars, l->data);
+  /* FIXME this is wrong, needs to be in the global accel resolution
+   * thing, to properly consider i18n etc., but that probably requires
+   * AccelGroup changes etc.
+   */
+  if (gdk_key_event_get_keyval (event) == keyval &&
+      ((gdk_event_get_modifier_state (event) & gtk_accelerator_get_default_mod_mask ()) ==
+       (mods & gtk_accelerator_get_default_mod_mask ())))
+    {
+      GList *tmp_menubars, *l;
+      GPtrArray *menubars;
+      GtkWidget *focus;
+      GtkWidget *first;
+
+      focus = gtk_window_get_focus (window);
+
+      if (priv->title_box != NULL &&
+          (focus == NULL || !gtk_widget_is_ancestor (focus, priv->title_box)) &&
+          gtk_widget_child_focus (priv->title_box, GTK_DIR_TAB_FORWARD))
+        return TRUE;
+
+      tmp_menubars = gtk_popover_menu_bar_get_viewable_menu_bars (window);
+      if (tmp_menubars == NULL)
+        return FALSE;
 
-  g_list_free (tmp_menubars);
+      menubars = g_ptr_array_sized_new (g_list_length (tmp_menubars));;
+      for (l = tmp_menubars; l; l = l->next)
+        g_ptr_array_add (menubars, l->data);
 
-  gtk_widget_focus_sort (GTK_WIDGET (window), GTK_DIR_TAB_FORWARD, menubars);
+      g_list_free (tmp_menubars);
 
-  first = g_ptr_array_index (menubars, 0);
-  gtk_popover_menu_bar_select_first (GTK_POPOVER_MENU_BAR (first));
+      gtk_widget_focus_sort (GTK_WIDGET (window), GTK_DIR_TAB_FORWARD, menubars);
 
-  g_ptr_array_free (menubars, TRUE);
+      first = g_ptr_array_index (menubars, 0);
+      gtk_popover_menu_bar_select_first (GTK_POPOVER_MENU_BAR (first));
 
-  return TRUE;
+      g_ptr_array_free (menubars, TRUE);
+
+      return TRUE;
+    }
+  return FALSE;
+}
+
+static void
+gtk_window_mnemonic_hash_foreach (guint      keyval,
+                                 GSList    *targets,
+                                 gpointer   data)
+{
+  struct {
+    GtkWindow *window;
+    GtkWindowKeysForeachFunc func;
+    gpointer func_data;
+  } *info = data;
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (info->window);
+
+  (*info->func) (info->window, keyval, priv->mnemonic_modifier, TRUE, info->func_data);
+}
+
+static void
+_gtk_window_keys_foreach (GtkWindow                *window,
+                         GtkWindowKeysForeachFunc func,
+                         gpointer                 func_data)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GSList *groups;
+  GtkMnemonicHash *mnemonic_hash;
+
+  struct {
+    GtkWindow *window;
+    GtkWindowKeysForeachFunc func;
+    gpointer func_data;
+  } info;
+
+  info.window = window;
+  info.func = func;
+  info.func_data = func_data;
+
+  mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+  if (mnemonic_hash)
+    _gtk_mnemonic_hash_foreach (mnemonic_hash,
+                               gtk_window_mnemonic_hash_foreach, &info);
+
+  groups = gtk_accel_groups_from_object (G_OBJECT (window));
+  while (groups)
+    {
+      GtkAccelGroup *group = groups->data;
+      gint i;
+
+      for (i = 0; i < group->priv->n_accels; i++)
+       {
+         GtkAccelKey *key = &group->priv->priv_accels[i].key;
+         
+         if (key->accel_key)
+           (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
+       }
+      
+      groups = groups->next;
+    }
+
+  if (priv->application)
+    {
+      GtkApplicationAccels *app_accels;
+
+      app_accels = gtk_application_get_application_accels (priv->application);
+      gtk_application_accels_foreach_key (app_accels, window, func, func_data);
+    }
 }
 
 static void
@@ -7429,6 +7912,7 @@ struct _GtkWindowKeyEntry
 {
   guint keyval;
   guint modifiers;
+  guint is_mnemonic : 1;
 };
 
 static void 
@@ -7437,6 +7921,35 @@ window_key_entry_destroy (gpointer data)
   g_slice_free (GtkWindowKeyEntry, data);
 }
 
+static void
+add_to_key_hash (GtkWindow      *window,
+                guint           keyval,
+                GdkModifierType modifiers,
+                gboolean        is_mnemonic,
+                gpointer        data)
+{
+  GtkKeyHash *key_hash = data;
+
+  GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
+
+  entry->keyval = keyval;
+  entry->modifiers = modifiers;
+  entry->is_mnemonic = is_mnemonic;
+
+  /* GtkAccelGroup stores lowercased accelerators. To deal
+   * with this, if <Shift> was specified, uppercase.
+   */
+  if (modifiers & GDK_SHIFT_MASK)
+    {
+      if (keyval == GDK_KEY_Tab)
+       keyval = GDK_KEY_ISO_Left_Tab;
+      else
+       keyval = gdk_keyval_to_upper (keyval);
+    }
+  
+  _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
+}
+
 static GtkKeyHash *
 gtk_window_get_key_hash (GtkWindow *window)
 {
@@ -7448,6 +7961,7 @@ gtk_window_get_key_hash (GtkWindow *window)
   
   key_hash = _gtk_key_hash_new (gdk_display_get_keymap (priv->display),
                                (GDestroyNotify)window_key_entry_destroy);
+  _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
 
   return key_hash;
@@ -7464,6 +7978,111 @@ gtk_window_free_key_hash (GtkWindow *window)
     }
 }
 
+/**
+ * gtk_window_activate_key:
+ * @window:  a #GtkWindow
+ * @event:   a #GdkEvent
+ *
+ * Activates mnemonics and accelerators for this #GtkWindow. This is normally
+ * called by the default ::key_press_event handler for toplevel windows,
+ * however in some cases it may be useful to call this directly when
+ * overriding the standard key handling for a toplevel window.
+ *
+ * Returns: %TRUE if a mnemonic or accelerator was found and activated.
+ */
+gboolean
+gtk_window_activate_key (GtkWindow *window,
+                        GdkEvent  *event)
+{
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GtkKeyHash *key_hash;
+  GtkWindowKeyEntry *found_entry = NULL;
+  gboolean enable_accels;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  if (!(gdk_event_get_event_type (event) == GDK_KEY_PRESS ||
+        gdk_event_get_event_type (event) == GDK_KEY_RELEASE))
+    return FALSE;
+
+  key_hash = gtk_window_get_key_hash (window);
+
+  if (key_hash)
+    {
+      GSList *tmp_list;
+      GSList *entries = _gtk_key_hash_lookup (key_hash,
+                                             gdk_key_event_get_keycode (event),
+                                              gdk_event_get_modifier_state (event),
+                                             gtk_accelerator_get_default_mod_mask (),
+                                             gdk_key_event_get_group (event));
+
+      g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+                    "gtk-enable-accels", &enable_accels,
+                    NULL);
+
+      for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
+       {
+         GtkWindowKeyEntry *entry = tmp_list->data;
+         if (entry->is_mnemonic)
+            {
+              found_entry = entry;
+              break;
+            }
+          else 
+            {
+              if (enable_accels && !found_entry)
+                {
+                 found_entry = entry;
+                }
+            }
+       }
+
+      g_slist_free (entries);
+    }
+
+  if (found_entry)
+    {
+      if (found_entry->is_mnemonic)
+        {
+          return gtk_window_mnemonic_activate (window, found_entry->keyval,
+                                               found_entry->modifiers);
+        }
+      else
+        {
+          if (enable_accels)
+            {
+              if (gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers))
+                return TRUE;
+
+              if (priv->application)
+                {
+                  GtkWidget *focused_widget;
+                  GtkActionMuxer *muxer;
+                  GtkApplicationAccels *app_accels;
+
+                  focused_widget = gtk_window_get_focus (window);
+
+                  if (focused_widget)
+                    muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE);
+                  else
+                    muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (window), FALSE);
+
+                  if (muxer == NULL)
+                    return FALSE;
+
+                  app_accels = gtk_application_get_application_accels (priv->application);
+                  return gtk_application_accels_activate (app_accels,
+                                                          G_ACTION_GROUP (muxer),
+                                                          found_entry->keyval, found_entry->modifiers);
+                }
+            }
+        }
+    }
+
+  return gtk_window_activate_menubar (window, event);
+}
+
 /*
  * _gtk_window_set_is_active:
  * @window: a #GtkWindow
index 2563ac5cac4e8522e9102608810c1e32562c53a6..8f4c964feeb55c716d4d4dfc756ec28108fec890 100644 (file)
@@ -97,6 +97,12 @@ GDK_AVAILABLE_IN_ALL
 void       gtk_window_set_startup_id           (GtkWindow           *window,
                                                 const gchar         *startup_id);
 GDK_AVAILABLE_IN_ALL
+void       gtk_window_add_accel_group          (GtkWindow           *window,
+                                               GtkAccelGroup       *accel_group);
+GDK_AVAILABLE_IN_ALL
+void       gtk_window_remove_accel_group       (GtkWindow           *window,
+                                               GtkAccelGroup       *accel_group);
+GDK_AVAILABLE_IN_ALL
 void       gtk_window_set_focus                (GtkWindow           *window,
                                                GtkWidget           *focus);
 GDK_AVAILABLE_IN_ALL
@@ -184,6 +190,31 @@ GDK_AVAILABLE_IN_ALL
 void       gtk_window_set_has_user_ref_count (GtkWindow *window,
                                               gboolean   setting);
 
+GDK_AVAILABLE_IN_ALL
+void     gtk_window_add_mnemonic          (GtkWindow       *window,
+                                          guint            keyval,
+                                          GtkWidget       *target);
+GDK_AVAILABLE_IN_ALL
+void     gtk_window_remove_mnemonic       (GtkWindow       *window,
+                                          guint            keyval,
+                                          GtkWidget       *target);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_window_mnemonic_activate     (GtkWindow       *window,
+                                          guint            keyval,
+                                          GdkModifierType  modifier);
+GDK_AVAILABLE_IN_ALL
+void     gtk_window_set_mnemonic_modifier (GtkWindow       *window,
+                                          GdkModifierType  modifier);
+GDK_AVAILABLE_IN_ALL
+GdkModifierType gtk_window_get_mnemonic_modifier (GtkWindow *window);
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_window_activate_key          (GtkWindow        *window,
+                                          GdkEvent         *event);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_window_propagate_key_event   (GtkWindow        *window,
+                                          GdkEvent         *event);
+
 GDK_AVAILABLE_IN_ALL
 void     gtk_window_present            (GtkWindow *window);
 GDK_AVAILABLE_IN_ALL
index 8192644b7251b73a69b222c13cf7f4250d4fa967..5fc156f8f9ed1a0890371587af4ed3e5421e2504 100644 (file)
@@ -56,6 +56,7 @@ void            gtk_window_check_resize            (GtkWindow     *self);
 typedef void (*GtkWindowKeysForeachFunc) (GtkWindow      *window,
                                           guint           keyval,
                                           GdkModifierType modifiers,
+                                          gboolean        is_mnemonic,
                                           gpointer        data);
 
 gboolean gtk_window_emit_close_request (GtkWindow *window);
index 126ce44b31ac0c189679e43483beac005fffc99e..2681e62e8128a83a24296c8cff42bebd71705860 100644 (file)
@@ -40,7 +40,6 @@
 #include "prop-list.h"
 #include "recorder.h"
 #include "resource-list.h"
-#include "shortcuts.h"
 #include "size-groups.h"
 #include "statistics.h"
 #include "visual.h"
@@ -75,7 +74,6 @@ gtk_inspector_init (void)
   g_type_ensure (GTK_TYPE_INSPECTOR_PROP_LIST);
   g_type_ensure (GTK_TYPE_INSPECTOR_RECORDER);
   g_type_ensure (GTK_TYPE_INSPECTOR_RESOURCE_LIST);
-  g_type_ensure (GTK_TYPE_INSPECTOR_SHORTCUTS);
   g_type_ensure (GTK_TYPE_INSPECTOR_SIZE_GROUPS);
   g_type_ensure (GTK_TYPE_INSPECTOR_STATISTICS);
   g_type_ensure (GTK_TYPE_INSPECTOR_VISUAL);
index 4f32b7563989d9f83d0884285922606a1790d57a..c945386d2d8edb02b2ae396d6776346a81433900 100644 (file)
@@ -28,7 +28,6 @@ inspector_sources = files(
   'recording.c',
   'renderrecording.c',
   'resource-list.c',
-  'shortcuts.c',
   'size-groups.c',
   'startrecording.c',
   'statistics.c',
diff --git a/gtk/inspector/shortcuts.c b/gtk/inspector/shortcuts.c
deleted file mode 100644 (file)
index 3f70837..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2020 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <glib/gi18n-lib.h>
-
-#include "shortcuts.h"
-#include "gtklabel.h"
-#include "gtklistbox.h"
-#include "gtksizegroup.h"
-#include "gtkstack.h"
-#include "gtkshortcut.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutcontroller.h"
-
-struct _GtkInspectorShortcuts
-{
-  GtkWidget parent;
-
-  GtkWidget *box;
-  GtkWidget *list;
-
-  GtkSizeGroup *trigger;
-  GtkSizeGroup *action;
-};
-
-G_DEFINE_TYPE (GtkInspectorShortcuts, gtk_inspector_shortcuts, GTK_TYPE_WIDGET)
-
-static void
-gtk_inspector_shortcuts_init (GtkInspectorShortcuts *sl)
-{
-  gtk_widget_init_template (GTK_WIDGET (sl));
-}
-
-static GtkWidget *
-create_row (gpointer item,
-            gpointer user_data)
-{
-  GtkShortcut *shortcut = GTK_SHORTCUT (item);
-  GtkInspectorShortcuts *sl = GTK_INSPECTOR_SHORTCUTS (user_data);
-  GtkShortcutTrigger *trigger;
-  GtkShortcutAction *action;
-  char *s;
-  GtkWidget *row;
-  GtkWidget *label;
-
-  trigger = gtk_shortcut_get_trigger (shortcut);
-  action = gtk_shortcut_get_action (shortcut);
-
-  row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
-
-  s = gtk_shortcut_trigger_to_string (trigger);
-  label = gtk_label_new (s);
-  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
-  g_free (s);
-  gtk_container_add (GTK_CONTAINER (row), label);
-  gtk_size_group_add_widget (sl->trigger, label);
-
-  s = gtk_shortcut_action_to_string (action);
-  label = gtk_label_new (s);
-  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
-  g_free (s);
-  gtk_container_add (GTK_CONTAINER (row), label);
-  gtk_size_group_add_widget (sl->action, label);
-
-  return row;
-}
-
-void
-gtk_inspector_shortcuts_set_object (GtkInspectorShortcuts *sl,
-                                    GObject               *object)
-{
-  GtkWidget *stack;
-  GtkStackPage *page;
-
-  stack = gtk_widget_get_parent (GTK_WIDGET (sl));
-  page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
-
-  if (GTK_IS_SHORTCUT_CONTROLLER (object))
-    {
-      g_object_set (page, "visible", TRUE, NULL);
-      gtk_list_box_bind_model (GTK_LIST_BOX (sl->list),
-                               G_LIST_MODEL (object),
-                               create_row,
-                               sl,
-                               NULL);
-    }
-  else
-    {
-      g_object_set (page, "visible", FALSE, NULL);
-      gtk_list_box_bind_model (GTK_LIST_BOX (sl->list),
-                               NULL,
-                               NULL,
-                               NULL,
-                               NULL);
-    }
-}
-
-static void
-gtk_inspector_shortcuts_measure (GtkWidget      *widget,
-                                 GtkOrientation  orientation,
-                                 int             for_size,
-                                 int            *minimum,
-                                 int            *natural,
-                                 int            *minimum_baseline,
-                                 int            *natural_baseline)
-{
-  GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (widget);
-
-  gtk_widget_measure (shortcuts->box,
-                      orientation,
-                      for_size,
-                      minimum, natural,
-                      minimum_baseline, natural_baseline);
-}
-
-static void
-gtk_inspector_shortcuts_size_allocate (GtkWidget *widget,
-                                       int        width,
-                                       int        height,
-                                       int        baseline)
-{
-  GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (widget);
-
-  gtk_widget_size_allocate (shortcuts->box,
-                            &(GtkAllocation) { 0, 0, width, height },
-                            baseline);
-}
-
-
-static void
-gtk_inspector_shortcuts_class_init (GtkInspectorShortcutsClass *klass)
-{
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
-  widget_class->measure = gtk_inspector_shortcuts_measure;
-  widget_class->size_allocate = gtk_inspector_shortcuts_size_allocate;
-
-  gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/shortcuts.ui");
-  gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, box);
-  gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, list);
-  gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, trigger);
-  gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, action);
-}
diff --git a/gtk/inspector/shortcuts.h b/gtk/inspector/shortcuts.h
deleted file mode 100644 (file)
index 145cb86..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2020 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _GTK_INSPECTOR_SHORTCUTS_H_
-#define _GTK_INSPECTOR_SHORTCUTS_H_
-
-#include <gtk/gtkbox.h>
-
-#define GTK_TYPE_INSPECTOR_SHORTCUTS (gtk_inspector_shortcuts_get_type ())
-
-G_DECLARE_FINAL_TYPE (GtkInspectorShortcuts, gtk_inspector_shortcuts, GTK, INSPECTOR_SHORTCUTS, GtkWidget)
-
-
-void gtk_inspector_shortcuts_set_object (GtkInspectorShortcuts *sl,
-                                         GObject               *object);
-
-#endif
diff --git a/gtk/inspector/shortcuts.ui b/gtk/inspector/shortcuts.ui
deleted file mode 100644 (file)
index 7ac55eb..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface domain="gtk40">
-  <template class="GtkInspectorShortcuts" parent="GtkWidget">
-    <style>
-      <class name="view"/>
-    </style>
-    <child>
-      <object class="GtkBox" id="box">
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkBox">
-            <style>
-              <class name="header"/>
-            </style>
-            <child>
-              <object class="GtkLabel" id="trigger_heading">
-                <property name="label" translatable="yes">Trigger</property>
-                <property name="xalign">0</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkLabel" id="action_heading">
-                <property name="label" translatable="yes">Action</property>
-                <property name="xalign">0</property>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkScrolledWindow">
-            <property name="hexpand">1</property>
-            <property name="vexpand">1</property>
-            <property name="hscrollbar-policy">never</property>
-            <child>
-              <object class="GtkListBox" id="list">
-                <style>
-                  <class name="list"/>
-                </style>
-                <property name="selection-mode">none</property>
-              </object>
-            </child>
-          </object>
-        </child>
-      </object>
-    </child>
-  </template>
-  <object class="GtkSizeGroup" id="trigger">
-    <property name="mode">horizontal</property>
-    <widgets>
-      <widget name="trigger_heading"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="action">
-    <property name="mode">horizontal</property>
-    <widgets>
-      <widget name="action_heading"/>
-    </widgets>
-  </object>
-</interface>
index 2b86655b43bbdce46898d7c542f3f6e940c9191b..6b4b2524d5a00ddbbdd75fc603dea0931f8699c1 100644 (file)
@@ -37,7 +37,6 @@
 #include "size-groups.h"
 #include "data-list.h"
 #include "actions.h"
-#include "shortcuts.h"
 #include "menu.h"
 #include "misc-info.h"
 #include "magnifier.h"
@@ -92,7 +91,6 @@ set_selected_object (GtkInspectorWindow *iw,
   gtk_inspector_size_groups_set_object (GTK_INSPECTOR_SIZE_GROUPS (iw->size_groups), selected);
   gtk_inspector_data_list_set_object (GTK_INSPECTOR_DATA_LIST (iw->data_list), selected);
   gtk_inspector_actions_set_object (GTK_INSPECTOR_ACTIONS (iw->actions), selected);
-  gtk_inspector_shortcuts_set_object (GTK_INSPECTOR_SHORTCUTS (iw->shortcuts), selected);
   gtk_inspector_menu_set_object (GTK_INSPECTOR_MENU (iw->menu), selected);
   gtk_inspector_controllers_set_object (GTK_INSPECTOR_CONTROLLERS (iw->controllers), selected);
   gtk_inspector_magnifier_set_object (GTK_INSPECTOR_MAGNIFIER (iw->magnifier), selected);
@@ -423,7 +421,6 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, size_groups);
   gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, data_list);
   gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, actions);
-  gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, shortcuts);
   gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, menu);
   gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, misc_info);
   gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, controllers);
index 6ac9a7eafc221938035508d1c9422bd4b5a18119..3f297061415b7d456c9adbff9fc44d9329894bf6 100644 (file)
@@ -66,7 +66,6 @@ typedef struct
   GtkWidget *size_groups;
   GtkWidget *data_list;
   GtkWidget *actions;
-  GtkWidget *shortcuts;
   GtkWidget *menu;
   GtkWidget *misc_info;
   GtkWidget *controllers;
index 4623a72229c18f8704fa9391e14d2fdf9cec35ae..963464be7a2d718e9f3c936efba713e6b45ba9ee 100644 (file)
                                     </property>
                                   </object>
                                 </child>
-                                <child>
-                                  <object class="GtkStackPage">
-                                    <property name="name">shortcuts</property>
-                                    <property name="title" translatable="yes">Shortcuts</property>
-                                    <property name="child">
-                                      <object class="GtkInspectorShortcuts" id="shortcuts">
-                                      </object>
-                                    </property>
-                                  </object>
-                                </child>
                               </object>
                             </child>
                           </object>
index 095b71158dfe2d09ddaed270ac9f659859238ce3..bf7e08a06ce0ecd1709d3141178e23eaba85833b 100644 (file)
@@ -119,6 +119,7 @@ gtk_private_sources = files([
   'gtkmenusectionbox.c',
   'gtkmenutracker.c',
   'gtkmenutrackeritem.c',
+  'gtkmnemonichash.c',
   'gtkpango.c',
   'gskpango.c',
   'gtkpathbar.c',
@@ -150,6 +151,7 @@ gtk_public_sources = files([
   'gtkaboutdialog.c',
   'gtkaccelgroup.c',
   'gtkaccellabel.c',
+  'gtkaccelmap.c',
   'gtkaccessible.c',
   'gtkactionable.c',
   'gtkactionbar.c',
@@ -164,6 +166,7 @@ gtk_public_sources = files([
   'gtkassistant.c',
   'gtkbin.c',
   'gtkbinlayout.c',
+  'gtkbindings.c',
   'gtkborder.c',
   'gtkboxlayout.c',
   'gtkbox.c',
@@ -199,7 +202,6 @@ gtk_public_sources = files([
   'gtkcombobox.c',
   'gtkcomboboxtext.c',
   'gtkcomposetable.c',
-  'gtkconcatmodel.c',
   'gtkconstraintguide.c',
   'gtkconstraintlayout.c',
   'gtkconstraint.c',
@@ -329,16 +331,11 @@ gtk_public_sources = files([
   'gtkselectionmodel.c',
   'gtkseparator.c',
   'gtksettings.c',
-  'gtkshortcut.c',
-  'gtkshortcutaction.c',
-  'gtkshortcutcontroller.c',
   'gtkshortcutlabel.c',
-  'gtkshortcutmanager.c',
   'gtkshortcutsgroup.c',
   'gtkshortcutssection.c',
   'gtkshortcutsshortcut.c',
   'gtkshortcutswindow.c',
-  'gtkshortcuttrigger.c',
   'gtkshow.c',
   'gtksidebarrow.c',
   'gtksingleselection.c',
@@ -405,6 +402,7 @@ gtk_public_headers = files([
   'gtkaboutdialog.h',
   'gtkaccelgroup.h',
   'gtkaccellabel.h',
+  'gtkaccelmap.h',
   'gtkaccessible.h',
   'gtkactionable.h',
   'gtkactionbar.h',
@@ -419,6 +417,7 @@ gtk_public_headers = files([
   'gtkassistant.h',
   'gtkbin.h',
   'gtkbinlayout.h',
+  'gtkbindings.h',
   'gtkborder.h',
   'gtkbox.h',
   'gtkboxlayout.h',
@@ -569,16 +568,11 @@ gtk_public_headers = files([
   'gtkselectionmodel.h',
   'gtkseparator.h',
   'gtksettings.h',
-  'gtkshortcut.h',
-  'gtkshortcutaction.h',
-  'gtkshortcutcontroller.h',
   'gtkshortcutlabel.h',
-  'gtkshortcutmanager.h',
   'gtkshortcutsgroup.h',
   'gtkshortcutssection.h',
   'gtkshortcutsshortcut.h',
   'gtkshortcutswindow.h',
-  'gtkshortcuttrigger.h',
   'gtkshow.h',
   'gtksingleselection.h',
   'gtksizegroup.h',
index d03b287278993f528bd3ee1e99e11bf077bc96cb..4075102a5e2bdada90c4b7fbdad06dc13f971e04 100644 (file)
             </child>
             <child>
               <object class="GtkColorScale" id="h_slider">
-                <property name="name">h</property>
                 <property name="can-focus">True</property>
                 <property name="orientation">vertical</property>
                 <property name="adjustment">h_adj</property>
                 <property name="draw-value">False</property>
                 <property name="has-origin">False</property>
+                <signal name="popup-menu" handler="popup_edit" swapped="no"/>
                 <layout>
                   <property name="left-attach">0</property>
                   <property name="top-attach">1</property>
@@ -97,7 +97,6 @@
             </child>
             <child>
               <object class="GtkColorScale" id="a_slider">
-                <property name="name">a</property>
                 <property name="can-focus">True</property>
                 <property name="adjustment">a_adj</property>
                 <property name="draw-value">False</property>
                 <style>
                   <class name="marks-before"/>
                 </style>
+                <signal name="popup-menu" handler="popup_edit" swapped="no"/>
                 <layout>
                   <property name="left-attach">1</property>
                   <property name="top-attach">2</property>
             </child>
             <child>
               <object class="GtkColorPlane" id="sv_plane">
-                <property name="name">sv</property>
                 <property name="width-request">300</property>
                 <property name="height-request">300</property>
                 <property name="can-focus">True</property>
                 <property name="h-adjustment">h_adj</property>
                 <property name="s-adjustment">s_adj</property>
                 <property name="v-adjustment">v_adj</property>
+                <signal name="popup-menu" handler="popup_edit" swapped="no"/>
                 <layout>
                   <property name="left-attach">1</property>
                   <property name="top-attach">1</property>
index dca1716e237e6c6304a0773c7582a68d451f336d..ff7ad061fd727f03e111bec7c5e4981af9966c73 100644 (file)
                                                 <signal name="pressed" handler="click_cb" swapped="no"/>
                                               </object>
                                             </child>
+                                            <child>
+                                              <object class="GtkEventControllerKey">
+                                                <signal name="key-pressed" handler="treeview_key_press_cb" swapped="no"/>
+                                              </object>
+                                            </child>
+                                            <signal name="popup-menu" handler="list_popup_menu_cb" swapped="no"/>
                                             <signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
                                             <signal name="row-activated" handler="list_row_activated" swapped="no"/>
                                             <signal name="keynav-failed" handler="browse_files_tree_view_keynav_failed_cb"/>
         </child>
       </object>
     </child>
+    <child>
+      <object class="GtkEventControllerKey">
+        <signal name="key-pressed" handler="widget_key_press_cb" swapped="no"/>
+      </object>
+    </child>
   </template>
   <object class="GtkSizeGroup" id="browse_path_bar_size_group">
     <property name="mode">vertical</property>
index 1177326b401f591278ed40ea1f9134abc63726e6..31b1473c8de9a8eed2eafaa226186be931d86a00 100644 (file)
         </child>
       </object>
     </child>
+    <child>
+      <object class="GtkGestureClick">
+        <property name="button">3</property>
+        <signal name="pressed" handler="pressed_cb" swapped="no"/>
+      </object>
+    </child>
   </template>
 </interface>
index 2c3bd928504999d30cbacc2bad7bee218117ad20..8929b238fafb13dcf84fc1c885561e62defbf6f8 100644 (file)
@@ -77,6 +77,7 @@ gtk/gtkapplicationwindow.c
 gtk/gtkaspectframe.c
 gtk/gtkassistant.c
 gtk/gtkbin.c
+gtk/gtkbindings.c
 gtk/gtkbookmarksmanager.c
 gtk/gtkbox.c
 gtk/gtkboxlayout.c
index 0be7778fed8ab2e66e3f1ad587fb0f7998ab31a7..644f28115e1e104a80198923c91bcbb795174434 100644 (file)
@@ -77,6 +77,7 @@ gtk/gtkapplicationwindow.c
 gtk/gtkaspectframe.c
 gtk/gtkassistant.c
 gtk/gtkbin.c
+gtk/gtkbindings.c
 gtk/gtkbookmarksmanager.c
 gtk/gtkbox.c
 gtk/gtkboxlayout.c
index 1f6b8c8439e7d73ba925f21207deae1ceeabccf8..4c591dfa497dde7a54df50594378e099561d5597 100644 (file)
@@ -1603,33 +1603,25 @@ create_listbox (GtkWidget *widget)
 
 
 static GtkWidget *
-accel_button_new (const gchar *text,
-                 const gchar *accel)
+accel_button_new (GtkAccelGroup *accel_group,
+                 const gchar   *text,
+                 const gchar   *accel)
 {
   guint keyval;
   GdkModifierType modifiers;
   GtkWidget *button;
   GtkWidget *label;
-  GtkEventController *controller;
-  GtkShortcut *shortcut;
 
-  if (!gtk_accelerator_parse (accel, &keyval, &modifiers))
-    {
-      g_assert_not_reached ();
-    }
+  gtk_accelerator_parse (accel, &keyval, &modifiers);
+  g_assert (keyval);
 
   button = gtk_button_new ();
-  controller = gtk_shortcut_controller_new ();
-  gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller), GTK_SHORTCUT_SCOPE_GLOBAL);
-  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
-  shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, modifiers),
-                               gtk_activate_action_new ());
-  gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
-  g_object_unref (shortcut);
-  gtk_widget_add_controller (button, controller);
+  gtk_widget_add_accelerator (button, "activate", accel_group,
+                             keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
 
   label = gtk_accel_label_new (text);
-  gtk_accel_label_set_accel (GTK_ACCEL_LABEL (label), keyval, modifiers);
+  gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
+  gtk_widget_show (label);
   
   gtk_container_add (GTK_CONTAINER (button), label);
 
@@ -1644,6 +1636,7 @@ create_key_lookup (GtkWidget *widget)
 
   if (!window)
     {
+      GtkAccelGroup *accel_group = gtk_accel_group_new ();
       GtkWidget *button;
       GtkWidget *content_area;
 
@@ -1658,6 +1651,8 @@ create_key_lookup (GtkWidget *widget)
        */
       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
 
+      gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
 
       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
@@ -1670,23 +1665,23 @@ create_key_lookup (GtkWidget *widget)
       gtk_container_add (GTK_CONTAINER (content_area), button);
       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 7", "<Alt><Shift>b");
+      button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 8", "<Alt>d");
+      button = accel_button_new (accel_group, "Button 8", "<Alt>d");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 9", "<Alt>Cyrillic_ve");
+      button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
       gtk_container_add (GTK_CONTAINER (content_area), button);
       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
       gtk_container_add (GTK_CONTAINER (content_area), button);
       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 12", "<Super>a");
+      button = accel_button_new (accel_group, "Button 12", "<Super>a");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 13", "<Hyper>a");
+      button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 14", "<Meta>a");
+      button = accel_button_new (accel_group, "Button 14", "<Meta>a");
       gtk_container_add (GTK_CONTAINER (content_area), button);
-      button = accel_button_new ("Button 15", "<Shift><Mod4>b");
+      button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
       gtk_container_add (GTK_CONTAINER (content_area), button);
 
       window_ptr = &window;
@@ -6237,6 +6232,7 @@ main (int argc, char *argv[])
 {
   GtkCssProvider *provider, *memory_provider;
   GdkDisplay *display;
+  GtkBindingSet *binding_set;
   int i;
   gboolean done_benchmarks = FALSE;
 
@@ -6320,6 +6316,15 @@ main (int argc, char *argv[])
   if (done_benchmarks)
     return 0;
 
+  /* bindings test
+   */
+  binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
+  gtk_binding_entry_add_signal (binding_set,
+                               '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
+                               "debug_msg",
+                               1,
+                               G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
+
   memory_provider = gtk_css_provider_new ();
   gtk_css_provider_load_from_data (memory_provider,
                                    "#testgtk-version-label {\n"
index cb2b647b0f3d081261bc48fb53f268b7e19be6ac..f165d88aa7713280274f79c3a4a8c10ae9a2f806 100644 (file)
@@ -40,6 +40,7 @@ int main (int argc, char **argv)
        GtkWidget *label;
        GtkWidget *check;
        GtkWidget *combo;
+       GtkAccelGroup *accel_group;
        guint i;
        guint row = 0;
        GMenu *menu;
@@ -54,6 +55,9 @@ int main (int argc, char **argv)
        gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
        gtk_container_add (GTK_CONTAINER (window), grid);
 
+       accel_group = gtk_accel_group_new ();
+       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
        /* horizontal alignment */
        label = gtk_label_new ("Horizontal Alignment:");
        gtk_widget_show (label);
diff --git a/testsuite/css/parser/at-invalid-22.css b/testsuite/css/parser/at-invalid-22.css
new file mode 100644 (file)
index 0000000..db96269
--- /dev/null
@@ -0,0 +1 @@
+@define-color color darker ( @blue ) ;
diff --git a/testsuite/css/parser/at-invalid-22.errors b/testsuite/css/parser/at-invalid-22.errors
new file mode 100644 (file)
index 0000000..168e43d
--- /dev/null
@@ -0,0 +1 @@
+at-invalid-22.css:1:21-27: error: GTK_CSS_PARSER_ERROR_SYNTAX
diff --git a/testsuite/css/parser/at-invalid-22.ref.css b/testsuite/css/parser/at-invalid-22.ref.css
new file mode 100644 (file)
index 0000000..e69de29
index e128e1971b4285c3f5cb7b4f3e8567f9ddc84859..ea4b815a591d40e24760e6f1add9af7a39c81797 100644 (file)
@@ -92,6 +92,9 @@ test_data = [
   'at-invalid-21.css',
   'at-invalid-21.errors',
   'at-invalid-21.ref.css',
+  'at-invalid-22.css',
+  'at-invalid-22.errors',
+  'at-invalid-22.ref.css',
   'at-valid-01.css',
   'at-valid-01.ref.css',
   'at-valid-02.css',
index c49a10e72fb9313e78a29162bdee51ab6ac460c5..da031da7bea4197660faaab9ff2536280117db42 100644 (file)
@@ -28,20 +28,19 @@ test_one_accel (const char *accel,
   char *label, *name;
 
   accel_key = 0;
-  g_assert (gtk_accelerator_parse_with_keycode (accel,
-                                                gdk_display_get_default (),
-                                                &accel_key,
-                                                &keycodes,
-                                                &mods));
+  gtk_accelerator_parse_with_keycode (accel,
+                                     &accel_key,
+                                     &keycodes,
+                                     &mods);
 
   if (has_keysym)
     {
       guint accel_key_2;
       GdkModifierType mods_2;
 
-      g_assert (gtk_accelerator_parse (accel,
-                                       &accel_key_2,
-                                       &mods_2));
+      gtk_accelerator_parse (accel,
+                             &accel_key_2,
+                             &mods_2);
       g_assert (accel_key == accel_key_2);
       g_assert (mods == mods_2);
     }
index f15dce7ac16c76f3149241817004c4af6ac94914..23a78fa23e3c6f5b330d800d4c81dcbecb1b9d14 100644 (file)
@@ -360,7 +360,6 @@ test_introspection (void)
   } expected[] = {
     { GTK_TYPE_TEXT, "text.undo", NULL, NULL },
     { GTK_TYPE_TEXT, "text.redo", NULL, NULL },
-    { GTK_TYPE_TEXT, "menu.popup", NULL, NULL },
     { GTK_TYPE_TEXT, "clipboard.cut", NULL, NULL },
     { GTK_TYPE_TEXT, "clipboard.copy", NULL, NULL },
     { GTK_TYPE_TEXT, "clipboard.paste", NULL, NULL },
@@ -379,9 +378,9 @@ test_introspection (void)
                                         &property))
     {
       g_assert (expected[i].owner == owner);
-      g_assert_cmpstr (expected[i].name, ==, name);
-      g_assert_cmpstr (expected[i].params, ==, params ? g_variant_type_peek_string (params) : NULL);
-      g_assert_cmpstr (expected[i].property, ==, property);
+      g_assert (strcmp (expected[i].name, name) == 0);
+      g_assert (g_strcmp0 (expected[i].params, params ? g_variant_type_peek_string (params) : NULL) == 0);
+      g_assert (g_strcmp0 (expected[i].property, property) == 0);
       i++;
     }
   g_assert (i == G_N_ELEMENTS (expected));
index c7178d476df6d44ed886db02555579b43d0ac0b8..15afb24c4da77472e086bd1c348c8429b897672e 100644 (file)
@@ -1389,6 +1389,58 @@ test_message_dialog (void)
   g_object_unref (builder);
 }
 
+static void
+test_accelerators (void)
+{
+  GtkBuilder *builder;
+  const gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "        <accelerator key=\"q\" modifiers=\"GDK_CONTROL_MASK\" signal=\"clicked\"/>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  const gchar *buffer2 =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkTreeView\" id=\"treeview1\">"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *window1;
+  GSList *accel_groups;
+  GObject *accel_group;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  window1 = gtk_builder_get_object (builder, "window1");
+  g_assert (window1);
+  g_assert (GTK_IS_WINDOW (window1));
+
+  accel_groups = gtk_accel_groups_from_object (window1);
+  g_assert (g_slist_length (accel_groups) == 1);
+  accel_group = g_slist_nth_data (accel_groups, 0);
+  g_assert (accel_group);
+
+  gtk_widget_destroy (GTK_WIDGET (window1));
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  window1 = gtk_builder_get_object (builder, "window1");
+  g_assert (window1);
+  g_assert (GTK_IS_WINDOW (window1));
+
+  accel_groups = gtk_accel_groups_from_object (window1);
+  g_assert_cmpint (g_slist_length (accel_groups), ==, 0);
+
+  gtk_widget_destroy (GTK_WIDGET (window1));
+  g_object_unref (builder);
+}
+
 static void
 test_widget (void)
 {
@@ -2445,6 +2497,7 @@ main (int argc, char **argv)
 #endif
   g_test_add_func ("/Builder/CellView", test_cell_view);
   g_test_add_func ("/Builder/Dialog", test_dialog);
+  g_test_add_func ("/Builder/Accelerators", test_accelerators);
   g_test_add_func ("/Builder/Widget", test_widget);
   g_test_add_func ("/Builder/Value From String", test_value_from_string);
   g_test_add_func ("/Builder/Reference Counting", test_reference_counting);
diff --git a/testsuite/gtk/concatmodel.c b/testsuite/gtk/concatmodel.c
deleted file mode 100644 (file)
index 3e6292b..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/* GtkRBTree tests.
- *
- * Copyright (C) 2011, Red Hat, Inc.
- * Authors: Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <locale.h>
-
-#include "../../gtk/gtkconcatmodelprivate.h"
-
-/* _gtk_rbtree_test */
-
-static GQuark number_quark;
-static GQuark changes_quark;
-
-static guint
-get (GListModel *model,
-     guint       position)
-{
-  GObject *object = g_list_model_get_item (model, position);
-  g_assert (object != NULL);
-  return GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark));
-}
-
-static char *
-model_to_string (GListModel *model)
-{
-  GString *string = g_string_new (NULL);
-  guint i;
-
-  for (i = 0; i < g_list_model_get_n_items (model); i++)
-    {
-      if (i > 0)
-        g_string_append (string, " ");
-      g_string_append_printf (string, "%u", get (model, i));
-    }
-
-  return g_string_free (string, FALSE);
-}
-
-static void
-add (GListStore *store,
-     guint       number)
-{
-  GObject *object;
-
-  /* o cannot be differentiated from NULL, so don't use it */
-  g_assert (number != 0);
-
-  object = g_object_new (G_TYPE_OBJECT, NULL);
-  g_object_set_qdata (object, number_quark, GUINT_TO_POINTER (number));
-  g_list_store_append (store, object);
-  g_object_unref (object);
-}
-
-static void
-remove (GListStore *store,
-        guint       position)
-{
-  g_list_store_remove (store, position);
-}
-
-#define assert_model(model, expected) G_STMT_START{ \
-  char *s = model_to_string (G_LIST_MODEL (model)); \
-  if (!g_str_equal (s, expected)) \
-     g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-         #model " == " #expected, s, "==", expected); \
-  g_free (s); \
-}G_STMT_END
-
-#define assert_changes(model, expected) G_STMT_START{ \
-  GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \
-  if (!g_str_equal (changes->str, expected)) \
-     g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-         #model " == " #expected, changes->str, "==", expected); \
-  g_string_set_size (changes, 0); \
-}G_STMT_END
-
-static GListStore *
-new_empty_store (void)
-{
-  return g_list_store_new (G_TYPE_OBJECT);
-}
-
-static GListStore *
-new_store (guint start,
-           guint end)
-{
-  GListStore *store = new_empty_store ();
-  guint i;
-
-  for (i = start; i <= end; i++)
-    add (store, i);
-
-  return store;
-}
-
-static void
-items_changed (GListModel *model,
-               guint       position,
-               guint       removed,
-               guint       added,
-               GString    *changes)
-{
-  g_assert (removed != 0 || added != 0);
-
-  if (changes->len)
-    g_string_append (changes, ", ");
-
-  if (removed == 1 && added == 0)
-    {
-      g_string_append_printf (changes, "-%u", position);
-    }
-  else if (removed == 0 && added == 1)
-    {
-      g_string_append_printf (changes, "+%u", position);
-    }
-  else
-    {
-      g_string_append_printf (changes, "%u", position);
-      if (removed > 0)
-        g_string_append_printf (changes, "-%u", removed);
-      if (added > 0)
-        g_string_append_printf (changes, "+%u", added);
-    }
-}
-
-static void
-free_changes (gpointer data)
-{
-  GString *changes = data;
-
-  /* all changes must have been checked via assert_changes() before */
-  g_assert_cmpstr (changes->str, ==, "");
-
-  g_string_free (changes, TRUE);
-}
-
-static GtkConcatModel *
-new_model (void)
-{
-  GtkConcatModel *model = gtk_concat_model_new (G_TYPE_OBJECT);
-  GString *changes;
-
-  changes = g_string_new ("");
-  g_object_set_qdata_full (G_OBJECT(model), changes_quark, changes, free_changes);
-  g_signal_connect (model, "items-changed", G_CALLBACK (items_changed), changes);
-
-  return model;
-}
-
-static void
-test_append (void)
-{
-  GListStore *store = new_store (1, 3);
-  GtkConcatModel *concat = new_model ();
-
-  gtk_concat_model_append (concat, G_LIST_MODEL (store));
-
-  assert_model (concat, "1 2 3");
-  assert_changes (concat, "0+3");
-
-  g_object_unref (store);
-  g_object_unref (concat);
-}
-
-static void
-test_append_and_add (void)
-{
-  GListStore *store = new_empty_store ();
-  GtkConcatModel *concat = new_model ();
-
-  gtk_concat_model_append (concat, G_LIST_MODEL (store));
-
-  add (store, 1);
-  add (store, 2);
-  add (store, 3);
-  assert_model (concat, "1 2 3");
-  assert_changes (concat, "+0, +1, +2");
-
-  g_object_unref (store);
-  g_object_unref (concat);
-}
-
-static void
-test_append_and_remove (void)
-{
-  GListStore *store = new_store (1, 3);
-  GtkConcatModel *concat = new_model ();
-
-  gtk_concat_model_append (concat, G_LIST_MODEL (store));
-  gtk_concat_model_remove (concat, G_LIST_MODEL (store));
-
-  assert_model (concat, "");
-  assert_changes (concat, "0+3, 0-3");
-
-  /* Check that all signal handlers are gone */
-  g_list_store_remove_all (store);
-
-  g_object_unref (store);
-  g_object_unref (concat);
-}
-
-static void
-test_append_and_remove_items (void)
-{
-  GListStore *store = new_empty_store ();
-  GtkConcatModel *concat = new_model ();
-
-  gtk_concat_model_append (concat, G_LIST_MODEL (store));
-
-  add (store, 1);
-  add (store, 2);
-  add (store, 3);
-  remove (store, 0);
-  remove (store, 1);
-  remove (store, 0);
-
-  assert_model (concat, "");
-  assert_changes (concat, "+0, +1, +2, -0, -1, -0");
-
-  g_object_unref (store);
-  g_object_unref (concat);
-}
-
-static void
-test_append_many (void)
-{
-  GListStore *store[5] = { new_store (1, 3), new_store (4, 4), new_store (5, 10), new_empty_store (), new_store (11, 20) };
-  GtkConcatModel *concat = new_model ();
-  guint i;
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
-
-  assert_model (concat, "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20");
-  assert_changes (concat, "0+3, +3, 4+6, 10+10");
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    g_object_unref (store[i]);
-  g_object_unref (concat);
-}
-
-static void
-test_append_many_and_add (void)
-{
-  GListStore *store[3];
-  GtkConcatModel *concat = new_model ();
-  guint i, j;
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    {
-      store[i] = new_empty_store ();
-      gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
-    }
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    {
-      for (j = 0; j < G_N_ELEMENTS (store); j++)
-        {
-          add (store[(i + j) % G_N_ELEMENTS (store)], i * 3 + j + 1);
-        }
-    }
-
-  assert_model (concat, "1 6 8 2 4 9 3 5 7");
-  assert_changes (concat, "+0, +1, +2, +2, +4, +1, +6, +2, +5");
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    g_object_unref (store[i]);
-  g_object_unref (concat);
-}
-
-static void
-test_append_many_and_remove (void)
-{
-  GListStore *store[5];
-  GtkConcatModel *concat = new_model ();
-  guint i;
-
-  store[0] = new_empty_store ();
-  gtk_concat_model_append (concat, G_LIST_MODEL (store[0]));
-  for (i = 1; i < G_N_ELEMENTS (store); i++)
-    {
-      store[i] = new_store (i * (i - 1) / 2 + 1, i * (i + 1) / 2);
-      gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
-    }
-
-  assert_model (concat, "1 2 3 4 5 6 7 8 9 10");
-  assert_changes (concat, "+0, 1+2, 3+3, 6+4");
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    {
-      gtk_concat_model_remove (concat, G_LIST_MODEL (store[(3 * i) % G_N_ELEMENTS (store)]));
-    }
-
-  assert_model (concat, "");
-  assert_changes (concat, "3-3, -0, 2-4, 0-2");
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    {
-      g_list_store_remove_all (store[i]);
-      g_object_unref (store[i]);
-    }
-
-  g_object_unref (concat);
-}
-
-static void
-test_append_many_and_remove_items (void)
-{
-  GListStore *store[5];
-  GtkConcatModel *concat = new_model ();
-  guint i;
-
-  store[0] = new_empty_store ();
-  gtk_concat_model_append (concat, G_LIST_MODEL (store[0]));
-  for (i = 1; i < G_N_ELEMENTS (store); i++)
-    {
-      store[i] = new_store (i * (i - 1) / 2 + 1, i * (i + 1) / 2);
-      gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
-    }
-
-  assert_model (concat, "1 2 3 4 5 6 7 8 9 10");
-  assert_changes (concat, "+0, 1+2, 3+3, 6+4");
-
-  for (i = 1; i < G_N_ELEMENTS (store); i++)
-    {
-      remove (store[i], 3 % i);
-    }
-
-  assert_model (concat, "2 5 6 7 8 9");
-  assert_changes (concat, "-0, -1, -1, -6");
-
-  for (i = 0; i < G_N_ELEMENTS (store); i++)
-    g_object_unref (store[i]);
-  g_object_unref (concat);
-}
-
-int
-main (int argc, char *argv[])
-{
-  g_test_init (&argc, &argv, NULL);
-  setlocale (LC_ALL, "C");
-  g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
-
-  number_quark = g_quark_from_static_string ("Hell and fire was spawned to be released.");
-  changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?");
-
-  g_test_add_func ("/compatmodel/append", test_append);
-  g_test_add_func ("/compatmodel/append_and_add", test_append_and_add);
-  g_test_add_func ("/compatmodel/append_and_remove", test_append_and_remove);
-  g_test_add_func ("/compatmodel/append_and_remove_items", test_append_and_remove_items);
-  g_test_add_func ("/compatmodel/append_many", test_append_many);
-  g_test_add_func ("/compatmodel/append_many_and_add", test_append_many_and_add);
-  g_test_add_func ("/compatmodel/append_many_and_remove", test_append_many_and_remove);
-  g_test_add_func ("/compatmodel/append_many_and_remove_items", test_append_many_and_remove_items);
-
-  return g_test_run ();
-}
index 4222c32b707eb811e7ec8e41506d6f201aa951ce..ab735dc48285e288bac22d0c3ef2634cbb1af482 100644 (file)
@@ -324,11 +324,6 @@ G_GNUC_END_IGNORE_DEPRECATIONS
       if (g_type_is_a (type, GTK_TYPE_SETTINGS))
         continue;
 
-      if (g_type_is_a (type, GTK_TYPE_SHORTCUT) &&
-         (strcmp (pspec->name, "action") == 0 ||
-           strcmp (pspec->name, "trigger") == 0))
-        continue;
-
       if (g_type_is_a (type, GTK_TYPE_SPIN_BUTTON) &&
           (strcmp (pspec->name, "adjustment") == 0))
         continue;
index 15c32cd2a3da95b98efd8276071f0976575f2036..983a33ffad10833ca12f18f4fe5617a6f1004ba6 100644 (file)
@@ -17,7 +17,6 @@ tests = [
   ['builderparser'],
   ['cellarea'],
   ['check-icon-names'],
-  ['concatmodel', ['../../gtk/gtkconcatmodel.c'], ['-DGTK_COMPILATION', '-UG_ENABLE_DEBUG']],
   ['constraint-solver', [
       '../../gtk/gtkconstraintsolver.c',
       '../../gtk/gtkconstraintexpression.c',
@@ -65,6 +64,7 @@ tests = [
   ['treepath'],
   ['treeview'],
   ['typename'],
+  ['window'],
   ['displayclose'],
   ['revealer-size'],
   ['widgetorder'],
@@ -72,10 +72,6 @@ tests = [
 
 # Tests that are expected to fail
 xfail = [
-  # one of the window resizing tests fails after
-  # the GdkToplevel refactoring, and needs a big
-  # gtkwindow.c configure request cleanup
-  'window',
 ]
 
 is_debug = get_option('buildtype').startswith('debug')